/* * tasking-multi.c * * Created on: Sep 8, 2011 * Author: Tiberiu */ #include #include #include Task* TaskList; Task* CurrentTask; uint32 NextPid = 1; void TaskSwitch (_RegsStack32* regs) { MagicBreakpoint(); if (!TaskList) return; uint32 eip = TaskReadEip(); if (eip == 0xABCDEF) return; // Save context asm volatile ("mov %%esp, %0" : "=r"(CurrentTask->Esp)); asm volatile ("mov %%ebp, %0" : "=r"(CurrentTask->Ebp)); CurrentTask->Eip = eip; // Next task CurrentTask = (!CurrentTask->Next) ? TaskList : CurrentTask->Next ; // Switch context PagingSwitchDirectory(CurrentTask->Pd); // Prepare for jump asm volatile ("" "mov %0, %%ebp; " "mov %1, %%esp; " "mov %2, %%ecx; " "mov $0xABCDEF, %%eax; " "jmp *%%ecx; " : : "r"(CurrentTask->Ebp), "r"(CurrentTask->Esp), "r"(CurrentTask->Eip) : "eax", "ecx"); } // Fallback for new tasks void TaskEnd () { // Find parent of current task if (CurrentTask->Pid == TaskList->Pid) TaskList = TaskList->Next; else { Task* t = TaskList; while (t->Next && t->Next->Pid != CurrentTask->Pid) t = t->Next; t->Next = CurrentTask->Next; } // Free allocated space kfree((void*)CurrentTask->StackLowerBase); kfree(CurrentTask); // Wait for next task for (;;) ; } void TaskCreate (void (*func)()) { // Create a new task Task* t = kmalloc(sizeof(Task)); // Set up data t->StackLowerBase = (uint32) kmalloc(0x1000); // Allocate some space for new stack t->StackUpperBase = t->StackLowerBase + 0x1000; t->Next = NULL; t->Pd = KernelDirectory; t->Pid = NextPid++; // Set up stack /*memset(&t->Regs, 0, sizeof(_RegsStack32)); t->Regs.ebp = t->StackUpperBase; t->Regs.esp = (t->StackUpperBase - 0x4 - sizeof(_RegsStack32)); t->Regs.useresp = t->StackUpperBase - 0x4; t->Regs.eip = (uint32) func; *(uint32 *) (t->Regs.esp) = (uint32) TaskEnd; // Fallback function t->Initialized = 0; // Read eflags asm volatile ("pushf; pop %0" : "=r"(t->Regs.eflags));*/ // Add the task to the list Task* last = TaskList; while (last && last->Next) last = last->Next; if (last) last->Next = t; } void TaskInitialize() { Task* t = kmalloc(sizeof(Task)); t->Pid = NextPid++; t->Pd = KernelDirectory; t->Next = NULL; TaskList = CurrentTask = t; }