feat: added reaper and suicide support
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user