feat: added reaper and suicide support

This commit is contained in:
2021-08-06 22:00:00 +02:00
parent ee4338fedd
commit be71f9a7e9
7 changed files with 87 additions and 18 deletions

View File

@@ -23,6 +23,7 @@
#include <myke/debug/debug.h>
#include <myke/util/slingurl.h>
#include <myke/libk/syscall.h>
#endif
@@ -53,6 +54,8 @@ void shutdown(const char *args);
void explode(const char *args);
void kill_self(const char* args);
void exec_self_test(const char *args);
void smash(const char *args);
@@ -67,8 +70,9 @@ cmd_handler cmd_handlers[] = {
{"print", print},
{"ide", ide},
{"shutdown", shutdown},
{"slingurl", slingurl},
#ifdef ENABLE_SELF_TEST
{"slingurl", slingurl},
{"kill-self", kill_self},
{"self-test", exec_self_test},
{"smash", smash},
{"explode", explode},
@@ -76,24 +80,27 @@ cmd_handler cmd_handlers[] = {
{NULL, NULL},
};
#ifdef ENABLE_SELF_TEST
void slingurl(const char *args) {
slingurl_decompose(args);
}
#ifdef ENABLE_SELF_TEST
void smash(const char *args) {
// smash the stack, should trigger the stack protector
char data[16];
memset(data, 'A', 32);
}
void kill_self(const char* args) {
syscall_kill_self();
}
void exec_self_test(const char *args) {
// unit tests
self_test();
}
void explode(const char *args) {
// trigger a divide by zero exception
uint32_t x = 0;

View File

@@ -23,6 +23,11 @@ void syscall_handle(isr_registers_t *registers) {
task_ensure_enabled();
task_suspend();
break;
case SYSCALL_KILL_SELF:
task_ensure_enabled();
task_end(task_get_current_tid());
task_switch_next();
break;
default:
break;
}

View File

@@ -35,3 +35,7 @@ void syscall_yield_irq(uint16_t irq) {
void syscall_job_suspend() {
syscall1(SYSCALL_SUSPEND);
}
void syscall_kill_self() {
syscall1(SYSCALL_KILL_SELF);
}

View File

@@ -10,6 +10,7 @@
#include <myke/cpu/cpu.h>
#include <myke/libk/libk.h>
#include <myke/mem/pmm.h>
#include <myke/libk/syscall.h>
#include <myke/tasks/task.h>
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
@@ -30,7 +31,7 @@ typedef struct task {
uint8_t state;
uint16_t wait_irq;
uint32_t tid;
pid_t tid;
int errno;
@@ -57,19 +58,23 @@ task_t *first_task = NULL;
task_t *last_task = NULL;
task_t *current_task = NULL;
uint32_t last_tid = 0;
pid_t last_tid = 0;
extern switch_task(task_registers_t
**, task_registers_t*);
pid_t reaper_pid = 0;
extern void switch_task(task_registers_t **, task_registers_t *);
extern att_cdecl att_noreturn void __task_entry_point();
extern att_noreturn void __task_entry_point_inner();
// internal api
void task_free(task_t* task);
// explicit cdecl calling convention
void att_cdecl att_noreturn task_entry_point(task_entrypoint entrypoint, void *entry_data) {
void att_unused att_cdecl att_noreturn task_entry_point(task_entrypoint entrypoint, void *entry_data) {
entrypoint(entry_data);
// task_end_self();
syscall_kill_self();
while (true); // halt
}
@@ -91,7 +96,7 @@ void task_lock_free() {
}
}
uint32_t task_get_current_tid() {
pid_t task_get_current_tid() {
return current_task->tid;
}
@@ -114,10 +119,47 @@ void task_suspend() {
task_switch_next();
}
// internal tasks
void att_noreturn task_idle(void *data) {
while (true) __asm__("hlt");
}
void att_noreturn task_reaper(void *data) {
while (true) {
bool did_reap = false;
task_lock_acquire();
task_t *t = first_task;
task_t *p = first_task;
task_t *n = NULL;
while (t != NULL) {
n = t->next;
if (t->state == TASK_STATE_STOPPED) {
did_reap = true;
if (t == first_task) {
if (n == NULL) {
k_panics("No more tasks");
}
first_task = n;
task_free(t);
t = NULL;
} else {
p->next = n;
task_free(t);
t = p;
}
}
p = t;
t = n;
}
task_lock_free();
if (did_reap) {
syscall_yield_job();
} else {
syscall_job_suspend();
}
}
}
void task_notify_irq(uint8_t irq_no) {
uint16_t irq__bit = 1 << irq_no;
task_t *t = first_task;
@@ -233,11 +275,17 @@ task_t *task_create(task_entrypoint entrypoint, void *entry_data) {
}
void task_init() {
idle_task = task_create(task_idle, NULL);
void task_free(task_t *task) {
pmm_free_pages(task->stack, 16);
free(task);
}
uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
void task_init() {
idle_task = task_create(task_idle, NULL);
reaper_pid = task_spawn(task_reaper, NULL);
}
pid_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
task_t *new_task = task_create(entrypoint, entry_data);
if (first_task == NULL) {
// first task
@@ -249,11 +297,12 @@ uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
return new_task->tid;
}
void task_end(uint32_t tid) {
void task_end(pid_t tid) {
task_t *t = first_task;
while (t != NULL) {
if (t->tid == tid) {
t->state = TASK_STATE_STOPPED;
task_signal(reaper_pid);
break;
}
t = t->next;