Hello!
I tried to have some threading capability with the help of `setjmp()` & `longjmp()` to save and restore context, and I failed. The calc complained with an error report like this:
Exception occured! (System ERROR)
0e0 Read address error (probably alignment)
PC=0810178a (Error location)
TEA=68532faa (Offending address)
TRA=0x0 (Trap number)
An unrecoverable error ...
Someone interested to look into it? Did I do something wrong, or is it possible at all?
Full source code is as following. I was guessing reg[7] to be stack pointer and overwrote it nearly blindly.
Code:
I tried to have some threading capability with the help of `setjmp()` & `longjmp()` to save and restore context, and I failed. The calc complained with an error report like this:
Quote:
Exception occured! (System ERROR)
0e0 Read address error (probably alignment)
PC=0810178a (Error location)
TEA=68532faa (Offending address)
TRA=0x0 (Trap number)
An unrecoverable error ...
Someone interested to look into it? Did I do something wrong, or is it possible at all?
Full source code is as following. I was guessing reg[7] to be stack pointer and overwrote it nearly blindly.
Code:
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/clock.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <setjmp.h>
#define TASK_CNT 3
#define STACK_SIZE 1024
typedef struct _task_t *task_handle_t;
typedef void (*task_func_t)(task_handle_t);
typedef struct _task_t {
jmp_buf env;
uint8_t stack[STACK_SIZE];
int id;
task_func_t func;
bool initialized;
} task_t;
static jmp_buf env_main;
static task_t tasks[TASK_CNT];
static void task_create(task_handle_t task, int id);
#define task_init(that) \
if(0== setjmp((that)->env)){ \
(that)->env->reg[7] = (uint32_t)((that)->stack + STACK_SIZE); \
(that)->initialized = true ; \
longjmp(env_main, (that)->id); \
}
#define task_yield(that) \
if(0== setjmp((that)->env)){ \
longjmp(env_main, (that)->id); \
}
static void task_run(task_handle_t that);
int main(void) {
for (int i = 0; i < TASK_CNT; ++i) {
task_create(tasks + i, 1 + i);
}
int id = setjmp(env_main);
if (0 == id) {
tasks[0].func(tasks);
} else {
int next = id;
if (next >= TASK_CNT) {
next = 0;
}
if (tasks[next].initialized) {
longjmp(tasks[next].env, 1);
} else {
tasks[next].func(tasks + next);
}
}
// ---------
for (;;) {
getkey();
}
return 0;
}
static void task_run(task_handle_t that) {
task_init(that);
char buf[64];
for (int i = 0;; ++i) {
sprintf(buf, "Task #%d running (%d)", that->id, i);
dclear(C_WHITE);
dtext(8, 48, C_BLACK, buf);
dupdate();
sleep_us(1000000);
task_yield(that);
} // for
}
static void task_create(task_handle_t task, int id) {
task->id = id;
task->func = task_run;
task->initialized = false;
}