diff options
Diffstat (limited to 'src/stem/task/task.c')
-rw-r--r-- | src/stem/task/task.c | 245 |
1 files changed, 0 insertions, 245 deletions
diff --git a/src/stem/task/task.c b/src/stem/task/task.c deleted file mode 100644 index 804adc2..0000000 --- a/src/stem/task/task.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "task.h" -#include <core/sys.h> -#include <core/monitor.h> -#include <mem/mem.h> -#include "timer.h" - -#define KSTACKSIZE 0x8000 - -//Static routines for handling threads exiting and all cleanup -static void thread_exit_stackJmp(uint32_t reason); -static void thread_exit2(uint32_t reason); -static void thread_delete(struct thread *th); -static void process_delete(struct process *pr); - -//From task_.asm -extern uint32_t read_eip(); -extern void task_idle(void*); - -static uint32_t thread_runnable(struct thread *th); - -static uint32_t nextpid = 1; - -struct process *processes = 0, *kernel_process; -struct thread *threads = 0, *current_thread = 0, *idle_thread; - -uint32_t tasking_tmpStack[0x4000]; - -void tasking_init() { - cli(); - kernel_process = kmalloc(sizeof(struct process)); //This process must be hidden to users - kernel_process->pid = kernel_process->uid = kernel_process->threads = 0; - kernel_process->privilege = PL_KERNEL; - kernel_process->parent = kernel_process; - kernel_process->pagedir = kernel_pagedir; - kernel_process->next = 0; - current_thread = 0; - idle_thread = thread_new(kernel_process, task_idle, 0); - threads = 0; //Do not include idle thread in threads - sti(); - monitor_write("Tasking set up\n"); -} - -static struct thread *thread_next() { - if (current_thread == 0 || current_thread == idle_thread) current_thread = threads; - struct thread *ret = current_thread; - while (1) { - ret = ret->next; - if (ret == 0) ret = threads; - if (thread_runnable(ret)) { - return ret; - } - if (ret == current_thread) return idle_thread; - } -} - -void tasking_switch() { - if (threads == 0) PANIC("No more threads to run !"); - asm volatile("cli"); - - uint32_t esp, ebp, eip; - - asm volatile("mov %%esp, %0" : "=r"(esp)); - asm volatile("mov %%ebp, %0" : "=r"(ebp)); - eip = read_eip(); - - if (eip == 0x12345) { - return; - } - - if (current_thread != 0) { - current_thread->esp = esp; - current_thread->ebp = ebp; - current_thread->eip = eip; - } - - current_thread = thread_next(); - - asm volatile(" \ - mov %0, %%ebp; \ - mov %1, %%esp; \ - mov %2, %%ecx; \ - mov $0x12345, %%eax; \ - jmp *%%ecx;" - : : "r"(current_thread->ebp), "r"(current_thread->esp), "r"(current_thread->eip)); -} - -void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) { - if (idx < 896) return; - struct process* it = processes; - while (it != 0) { - it->pagedir->tables[idx] = table; - it->pagedir->tablesPhysical[idx] = tablephysical; - it = it->next; - } -} - -uint32_t tasking_handleException(struct registers *regs) { - if (current_thread == 0) return 0; //No tasking yet - monitor_write("\n(task.c:99) Unhandled exception : "); - char *exception_messages[] = {"Division By Zero","Debug","Non Maskable Interrupt","Breakpoint", - "Into Detected Overflow","Out of Bounds","Invalid Opcode","No Coprocessor", "Double Fault", - "Coprocessor Segment Overrun","Bad TSS","Segment Not Present","Stack Fault","General Protection Fault", - "Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check"}; - monitor_write(exception_messages[regs->int_no]); - monitor_write(" at "); monitor_writeHex(regs->eip); - monitor_write(" >>> Thread exiting.\n"); - thread_exit_stackJmp(EX_TH_EXCEPTION); - PANIC("This should never have happened. Please report this."); -} - -void thread_sleep(uint32_t msecs) { - if (current_thread == 0) return; - current_thread->state = TS_SLEEPING; - current_thread->timeWait = timer_time() + msecs; - asm volatile("int $64" : : "a"(1)); -} - -void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h - /* - * if reason == EX_TH_NORMAL, it is just one thread exiting because it has to - * if reason == EX_TH_EXCEPTION, it is just one thread exiting because of an exception - * if reason is none of the two cases above, it is the whole process exiting (with error code = reason) - */ - struct thread *th = current_thread; - struct process *pr = th->process; - if ((reason == EX_TH_NORMAL || reason == EX_TH_EXCEPTION) && pr->threads > 1) { - thread_delete(th); - } else { - process_delete(pr); - } - sti(); - tasking_switch(); -} - -void thread_exit_stackJmp(uint32_t reason) { - uint32_t *stack; - cli(); - stack = tasking_tmpStack + 0x4000; - stack--; *stack = reason; - stack--; *stack = 0; - asm volatile(" \ - mov %0, %%esp; \ - mov %1, %%ebp; \ - mov %2, %%ecx; \ - mov %3, %%cr3; \ - jmp *%%ecx;" : : - "r"(stack), "r"(stack), "r"(thread_exit2), "r"(kernel_pagedir->physicalAddr)); -} - -void thread_exit() { - thread_exit_stackJmp(EX_TH_NORMAL); -} - -void process_exit(uint32_t retval) { - if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION; - thread_exit_stackJmp(retval); -} - -static uint32_t thread_runnable(struct thread *t) { - if (t->state == TS_RUNNING) return 1; - if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) return 1; - return 0; -} - -static void thread_run(struct thread *thread, thread_entry entry_point, void *data) { - pagedir_switch(thread->process->pagedir); //TODO : take into account privilege level - asm volatile("sti"); - entry_point(data); - thread_exit(0); -} - -struct thread *thread_new(struct process *proc, thread_entry entry_point, void *data) { - struct thread *t = kmalloc(sizeof(struct thread)); - t->process = proc; - proc->threads++; - t->kernelStack_addr = kmalloc(KSTACKSIZE); - t->kernelStack_size = KSTACKSIZE; - - uint32_t *stack = (uint32_t*)((size_t)t->kernelStack_addr + t->kernelStack_size); - - //Pass parameters - stack--; *stack = (uint32_t)data; - stack--; *stack = (uint32_t)entry_point; - stack--; *stack = (uint32_t)t; - stack--; *stack = 0; - t->esp = (uint32_t)stack; - t->ebp = t->esp + 8; - t->eip = (uint32_t)thread_run; - - t->state = TS_RUNNING; - - if (threads == 0) { - threads = t; - } else { - struct thread *i = threads; - while (i->next != 0) i = i->next; - i->next = t; - } - return t; -} - -struct process *process_new(struct process* parent, uint32_t uid, uint32_t privilege) { - struct process* p = kmalloc(sizeof(struct process)); - p->pid = (nextpid++); - p->uid = uid; - p->threads = 0; - p->privilege = privilege; - p->parent = parent; - p->pagedir = pagedir_new(); - p->next = processes; - processes = p; - return p; -} - -static void thread_delete(struct thread *th) { - kfree(th->kernelStack_addr); - th->process->threads--; - if (threads == th) { - threads = th->next; - } else { - struct thread *it = threads; - while (it->next != th && it->next != 0) it = it->next; - if (it->next == th) it->next = th->next; - } - kfree(th); -} - -static void process_delete(struct process *pr) { - struct thread *it; - while (threads != 0 && threads->process == pr) thread_delete(threads); - it = threads; - while (it != 0) { - while (it->next->process == pr) thread_delete(it->next); - it = it->next; - } - pagedir_delete(pr->pagedir); - if (processes == pr) { - processes = pr->next; - } else { - struct process *it = processes; - while (it != 0 && it->next != pr) it = it->next; - if (it != 0 && it->next == pr) it->next = pr->next; - } - kfree(pr); -} |