merge job and wren APIs

This commit is contained in:
Babz 2021-09-13 23:17:06 +02:00
parent d79d13b180
commit b795821e8e
4 changed files with 78 additions and 68 deletions

View File

@ -1,8 +1,11 @@
#include "job.h"
#include <string.h>
#include <gint/kmalloc.h>
#include "term.h"
#include "wren_utils.h"
extern jmp_buf sched_ctxbuf;
@ -10,6 +13,50 @@ WrenVM *job_vms[UNS_MAX_JOBS] = {0};
void *job_stacks[UNS_MAX_JOBS] = {0};
int current_job_id = -1;
static const char *new_job_name;
static const char *new_job_source;
extern volatile int must_yield;
__attribute__((noreturn)) static void run_vm(void) {
const int job_id = current_job_id;
term_kprint("copy input data...");
const int name_len = strlen(new_job_name);
const int prgm_len = strlen(new_job_source);
const int total_len = name_len + prgm_len + 2;
char *prgm_buf = kmalloc(total_len, NULL);
if (prgm_buf == NULL) {
term_eprintf("kmalloc(%d, NULL) failed", total_len);
longjmp(sched_ctxbuf, 2); // job exit point
}
strcpy(prgm_buf, new_job_name);
strcpy(prgm_buf + name_len + 1, new_job_source);
// now the gloabl static strings can be freed
term_kprint("create wren VM...");
WrenConfiguration config;
init_wren_config(&config);
must_yield = 0;
WrenVM *vm = wrenNewVM(&config);
job_vms[job_id] = vm; // place the newly created vm in its slot for later resume
term_kprint("start interpreter...");
must_yield = 1; // yield ASAP
wrenInterpret(vm, new_job_name, new_job_source);
term_kprint("interpreter returned");
// free resources (stack will be freed by the scheduler)
wrenFreeVM(job_vms[job_id]);
job_vms[job_id] = NULL;
kfree(prgm_buf);
// never return !!!
// longjmp to scheduler instead
// return value of 2 means job exit
longjmp(sched_ctxbuf, 2);
}
static void *job_start_(const uint32_t entry_point) {
term_kprint("allocate new stack...");
static const int job_stack_size = 64 * 1024; // 64 kiB stack
@ -35,11 +82,14 @@ static void *job_start_(const uint32_t entry_point) {
return (void *)child_stack; // then return the stack descriptor (not "stack pointer"!) for later free
}
int job_start(uint32_t entry_point) {
int job_start(const char *name, const char *source) {
new_job_name = name;
new_job_source = source;
for (int i = 0; i < UNS_MAX_JOBS; i++) {
if (job_vms[i] == NULL) {
current_job_id = i;
job_stacks[i] = job_start_(entry_point);
job_stacks[i] = job_start_((uint32_t)run_vm);
return i;
}
}
@ -53,8 +103,11 @@ void job_resume(int job_id) {
}
void job_free(int job_id) {
wrenFreeVM(job_vms[job_id]);
job_vms[job_id] = NULL;
// just in case something failed
if (job_vms[job_id] != NULL) {
wrenFreeVM(job_vms[job_id]);
job_vms[job_id] = NULL;
}
kfree(job_stacks[job_id]);
job_stacks[job_id] = NULL;

View File

@ -10,7 +10,7 @@ extern WrenVM *job_vms[UNS_MAX_JOBS];
extern void *job_stacks[UNS_MAX_JOBS];
extern int current_job_id;
int job_start(uint32_t entry_point);
int job_start(const char *name, const char *source);
void job_resume(int job_id);
void job_free(int job_id);

View File

@ -95,66 +95,6 @@ static void check_keyevents(void) {
}
}
__attribute__((noreturn)) static void run_vm_1(void) {
WrenConfiguration config;
init_wren_config(&config);
term_kprint("create wren VM...");
must_yield = 0;
WrenVM *vm = wrenNewVM(&config);
job_vms[current_job_id] = vm;
term_kprint("start interpreter...");
must_yield = 1; // yield ASAP
wrenInterpret(vm, "my_module",
"System.print(\"inner start\")\n"
"var i = 0\n"
"while (i < 30000) {\n"
" if ((i % 500) == 0) {\n"
" System.write(\"vm 1: i=%(i)\\n\")\n"
" }\n"
" i = i + 1\n"
"}\n"
"System.print(\"inner end\")\n");
term_kprint("interpreter returned");
// never return !!!
// longjmp to scheduler instead
// return value of 2 means job exit
longjmp(sched_ctxbuf, 2);
}
__attribute__((noreturn)) static void run_vm_2(void) {
WrenConfiguration config;
init_wren_config(&config);
term_kprint("create wren VM...");
must_yield = 0;
WrenVM *vm = wrenNewVM(&config);
job_vms[current_job_id] = vm;
term_kprint("start interpreter...");
must_yield = 1; // yield ASAP
wrenInterpret(vm, "my_module_2",
"System.print(\"inner start\")\n"
"var i = 0\n"
"while (i < 30000) {\n"
" if ((i % 500) == 0) {\n"
" System.write(\"vm 2: i=%(i)\\n\")\n"
" }\n"
" i = i + 1\n"
"}\n"
"System.print(\"inner end\")\n");
term_kprint("interpreter returned");
// never return !!!
// longjmp to scheduler instead
// return value of 2 means job exit
longjmp(sched_ctxbuf, 2);
}
int main(int isappli, int optnum) {
term_kprintf("main(%d, %d)", isappli, optnum);
@ -164,8 +104,25 @@ int main(int isappli, int optnum) {
timer_start(timer_redraw);
// start a few jobs
job_start((uint32_t)run_vm_1);
job_start((uint32_t)run_vm_2);
job_start("test_job_1", "System.print(\"inner start\")\n"
"var i = 0\n"
"while (i < 30000) {\n"
" if ((i % 500) == 0) {\n"
" System.write(\"vm 1: i=%(i)\\n\")\n"
" }\n"
" i = i + 1\n"
"}\n"
"System.print(\"inner end\")\n");
job_start("test_job_2", "System.print(\"inner start\")\n"
"var i = 0\n"
"while (i < 30000) {\n"
" if ((i % 500) == 0) {\n"
" System.write(\"vm 2: i=%(i)\\n\")\n"
" }\n"
" i = i + 1\n"
"}\n"
"System.print(\"inner end\")\n");
while (1) {
// system routine

View File

@ -35,4 +35,4 @@ void init_wren_config(WrenConfiguration *config) {
config->heapGrowthPercent = 50;
config->writeFn = &wn_write;
config->errorFn = &wn_error;
}
}