nshell/src/job.c

74 lines
1.9 KiB
C

#include "job.h"
#include <gint/kmalloc.h>
#include "term.h"
extern jmp_buf sched_ctxbuf;
WrenVM *job_vms[UNS_MAX_JOBS] = {0};
void *job_stacks[UNS_MAX_JOBS] = {0};
int current_job_id = -1;
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
const uint32_t child_stack = (uint32_t)kmalloc(job_stack_size, NULL);
const uint32_t new_sp = ((child_stack + 3) >> 2 << 2) + ((job_stack_size + 3) >> 2 << 2);
term_kprintf("new_bp=0x%08x", child_stack);
term_kprintf("new_sp=0x%08x", new_sp);
// get a copy of the current context
jmp_buf ctx;
setjmp(ctx);
// transform it to the hidden representation so we can modify it
struct __jmp_buf *ctx_ptr = &ctx[0];
ctx_ptr->reg[7] = new_sp; // change stack pointer
ctx_ptr->pr = entry_point; // change pc backup
const int ret = setjmp(sched_ctxbuf);
if (ret == 0)
longjmp(ctx, 1); // apply changes, run job until it yields a first time
else
return (void *)child_stack; // then return the stack descriptor (not "stack pointer"!) for later free
}
int job_start(uint32_t entry_point) {
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);
return i;
}
}
// no slot found
return -1;
}
void job_resume(int job_id) {
wrenResume(job_vms[job_id]); // longjmp(vm->ctxbuf, 1);
}
void job_free(int job_id) {
wrenFreeVM(job_vms[job_id]);
job_vms[job_id] = NULL;
kfree(job_stacks[job_id]);
job_stacks[job_id] = NULL;
}
void next_job(void) {
for (int i = 1; i < UNS_MAX_JOBS + 1; i++) {
const int candidate = (current_job_id + i) % UNS_MAX_JOBS;
if (job_stacks[candidate] != NULL) {
current_job_id = candidate;
return;
}
}
current_job_id = -1;
}