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

@@ -11,6 +11,7 @@
// function // function
#define att_noreturn __attribute((noreturn)) #define att_noreturn __attribute((noreturn))
#define att_cdecl __attribute((cdecl)) #define att_cdecl __attribute((cdecl))
#define att_unused __attribute((unused))
// structure // structure
#define att_packed __attribute((packed)) #define att_packed __attribute((packed))
// field // field

View File

@@ -12,6 +12,7 @@
#define SYSCALL_YIELD_JOB 0x02 #define SYSCALL_YIELD_JOB 0x02
#define SYSCALL_YIELD_IRQ 0x03 #define SYSCALL_YIELD_IRQ 0x03
#define SYSCALL_SUSPEND 0x04 #define SYSCALL_SUSPEND 0x04
#define SYSCALL_KILL_SELF 0x05
void att_noreturn syscall_start_scheduler(); void att_noreturn syscall_start_scheduler();
@@ -21,4 +22,6 @@ void syscall_yield_irq(uint16_t irq);
void syscall_job_suspend(); void syscall_job_suspend();
void syscall_kill_self();
#endif //NEW_KERNEL_SYSCALL_H #endif //NEW_KERNEL_SYSCALL_H

View File

@@ -19,13 +19,13 @@ void task_start_first();
void task_switch_next(); void task_switch_next();
uint32_t task_spawn(task_entrypoint, void *entry_data); pid_t task_spawn(task_entrypoint, void *entry_data);
void task_end(uint32_t tid); void task_end(pid_t tid);
void task_suspend(); void task_suspend();
uint32_t task_get_current_tid(); pid_t task_get_current_tid();
void task_signal(uint32_t tid); void task_signal(uint32_t tid);

View File

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

View File

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

View File

@@ -35,3 +35,7 @@ void syscall_yield_irq(uint16_t irq) {
void syscall_job_suspend() { void syscall_job_suspend() {
syscall1(SYSCALL_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/cpu/cpu.h>
#include <myke/libk/libk.h> #include <myke/libk/libk.h>
#include <myke/mem/pmm.h> #include <myke/mem/pmm.h>
#include <myke/libk/syscall.h>
#include <myke/tasks/task.h> #include <myke/tasks/task.h>
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE)) #define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
@@ -30,7 +31,7 @@ typedef struct task {
uint8_t state; uint8_t state;
uint16_t wait_irq; uint16_t wait_irq;
uint32_t tid; pid_t tid;
int errno; int errno;
@@ -57,19 +58,23 @@ task_t *first_task = NULL;
task_t *last_task = NULL; task_t *last_task = NULL;
task_t *current_task = NULL; task_t *current_task = NULL;
uint32_t last_tid = 0; pid_t last_tid = 0;
extern switch_task(task_registers_t pid_t reaper_pid = 0;
**, task_registers_t*);
extern void switch_task(task_registers_t **, task_registers_t *);
extern att_cdecl att_noreturn void __task_entry_point(); extern att_cdecl att_noreturn void __task_entry_point();
extern att_noreturn void __task_entry_point_inner(); extern att_noreturn void __task_entry_point_inner();
// internal api
void task_free(task_t* task);
// explicit cdecl calling convention // 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); entrypoint(entry_data);
// task_end_self(); syscall_kill_self();
while (true); // halt 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; return current_task->tid;
} }
@@ -114,10 +119,47 @@ void task_suspend() {
task_switch_next(); task_switch_next();
} }
// internal tasks
void att_noreturn task_idle(void *data) { void att_noreturn task_idle(void *data) {
while (true) __asm__("hlt"); 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) { void task_notify_irq(uint8_t irq_no) {
uint16_t irq__bit = 1 << irq_no; uint16_t irq__bit = 1 << irq_no;
task_t *t = first_task; task_t *t = first_task;
@@ -233,11 +275,17 @@ task_t *task_create(task_entrypoint entrypoint, void *entry_data) {
} }
void task_init() { void task_free(task_t *task) {
idle_task = task_create(task_idle, NULL); 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); task_t *new_task = task_create(entrypoint, entry_data);
if (first_task == NULL) { if (first_task == NULL) {
// first task // first task
@@ -249,11 +297,12 @@ uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
return new_task->tid; return new_task->tid;
} }
void task_end(uint32_t tid) { void task_end(pid_t tid) {
task_t *t = first_task; task_t *t = first_task;
while (t != NULL) { while (t != NULL) {
if (t->tid == tid) { if (t->tid == tid) {
t->state = TASK_STATE_STOPPED; t->state = TASK_STATE_STOPPED;
task_signal(reaper_pid);
break; break;
} }
t = t->next; t = t->next;