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

@@ -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;