#include "task.h" #include "alloc.h" #include "debug.h" #include "interrupts.h" #include "kpanic.h" #include "kprintf.h" #include "memory.h" #include "string.h" #include #include u32 esp_backup; struct task *create_task(u8 uid) { static u32 pid = 1; struct task *new_task = vmalloc(sizeof(struct task)); if (!new_task) return NULL; new_task->next = current_task->next; new_task->prev = current_task; current_task->next = new_task; new_task->status = RUN; new_task->uid = uid; new_task->esp0 = alloc_pages(STACK_SIZE, NULL); if (!new_task->esp0) { vfree(new_task); return NULL; } new_task->esp = new_task->esp0 + STACK_SIZE; new_task->pid = pid++; new_task->heap = alloc_pages(4096, (void **)&new_task->cr3); if (!new_task->heap) { free_pages(new_task->esp0, STACK_SIZE); vfree(new_task); return NULL; } return new_task; } i8 create_kernel_task(void) { struct task *new_task = vmalloc(sizeof(struct task)); if (!new_task) return -1; new_task->status = RUN; new_task->uid = 0; new_task->pid = 0; new_task->heap = page_directory; new_task->cr3 = page_directory - KERNEL_START; new_task->prev = new_task; new_task->next = new_task; current_task = new_task; return 0; } void exec_fn(void (*fn)(void)) { struct task *new_task = create_task(OWNER_KERNEL); if (!new_task) kpanic("failed to create new task"); new_task->eip = (u32 *)fn; } void zombify_task(struct task *task) { cli(); // Technically useless free_pages(task->heap, 4096); free_pages(task->esp0, STACK_SIZE); task->esp0 = NULL; task->heap = NULL; toris(); } void remove_task(struct task *task) { cli(); struct task *left = task->prev; struct task *right = task->next; if (task->child) { remove_task(task->child); task->child = NULL; } if (task->heap) free_pages(task->heap, 4096); if (task->esp0) free_pages(task->esp0, STACK_SIZE); left->next = right; right->prev = left; vfree(task); toris(); } struct task *copy_task(const struct task *task) { struct task *new_task = create_task(task->uid); if (!new_task) return NULL; memcpy(new_task->esp0, task->esp0, STACK_SIZE); new_task->esp = new_task->esp0 + (task->esp - task->esp0); new_task->status = task->status; return new_task; } void exit_task(void) { cli(); if (current_task->daddy && current_task->daddy->status != WAIT) current_task->status = ZOMBIE; else { if (current_task->daddy->status == WAIT) current_task->daddy->status = RUN; current_task->status = STOPPED; } toris(); scheduler(); }