/* * This file is in control of initialising the tasking subsystem. It also * implements the Task object. */ #include #include #include #include #include #include #include void init_scheduler(void); void timer_handler(struct InterruptFrame *frame); static void *task_new(void); static void task_delete(Object *); /* Task object type */ ObjectType taskType = { .new = task_new, .delete = task_delete, }; Task *currentTask[MAX_CPUS]; pid_t nextTid = 1; /* Create a new Task */ static void * task_new(void) { Task *task = kmalloc(sizeof(Task)); task->tid = nextTid++; task->priority = NORMAL; task->state = READY; return task; } /* Destroy a Task */ static void task_delete(Object *obj) { kfree(obj); } extern char stackTop[]; /* Move the stack */ static void move_stack(uintptr_t top, size_t size) { size_t offset; uintptr_t oldStack, oldBase; uintptr_t newStack, newBase; top -= sizeof(uintptr_t); asm volatile("mov %%esp, %0" : "=r" (oldStack)); asm volatile("mov %%ebp, %0" : "=r" (oldBase)); offset = top - (uintptr_t) stackTop; newStack = oldStack + offset; newBase = oldBase + offset; memcpy((void *) newStack, (void *) oldStack, (size_t) stackTop - oldStack); /* Update pointers on the stack */ uintptr_t i, tmp; for (i = top; i > top - size; i -= sizeof(uintptr_t)) { tmp = *(uintptr_t *) i; if (tmp > oldStack && tmp < (uintptr_t) stackTop) { tmp += offset; *(uintptr_t *) i = tmp; } } asm volatile("mov %0, %%esp" :: "r" (newStack)); asm volatile("mov %0, %%ebp" :: "r" (newBase)); } /* Initialise tasking */ void init_tasking(void) { move_stack(0xF0800000, 0x2000); current = new(&taskType); asm volatile("mov %%cr3, %0" : "=r" (current->pageDir)); init_scheduler(); register_interrupt(0, timer_handler); }