/* * tasking-multi.c * * Created on: Sep 8, 2011 * Author: Tiberiu */ #include #include Task* TaskList; Task* CurrentTask; uint32 NextPid = 1; void TaskSwitch () { if (!TaskList) return; // Save context asm volatile ("mov %%esp, %0" : "=r"(CurrentTask->Esp)); // Stack pointer asm volatile ("mov %%ebp, %0" : "=r"(CurrentTask->Ebp)); // Base pointer CurrentTask->Pd = CurrentDirectory; // Next task CurrentTask = (!CurrentTask->Next) ? TaskList : CurrentTask->Next ; // Switch context PagingSwitchDirectory(CurrentTask->Pd); asm volatile ("mov %0, %%esp" : : "r"(CurrentTask->Esp)); // Stack pointer asm volatile ("mov %0, %%ebp" : : "r"(CurrentTask->Ebp)); // Base pointer } // 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 *(uint32 *) (t->StackUpperBase - 0x4) = (uint32) TaskEnd; // Fallback function t->Ebp = (uint32) t->StackUpperBase; _RegsStack32* regs = (_RegsStack32*) (t->StackUpperBase - 0x4 - sizeof(_RegsStack32)); asm volatile ("mov %%ss, %0" : "=r" (regs->ss)); asm volatile ("mov %%cs, %0" : "=r" (regs->cs)); asm volatile ("pushf; pop %0" : "=r" (regs->eflags)); asm volatile ("mov %%esi, %0" : "=r" (regs->esi)); asm volatile ("mov %%edi, %0" : "=r" (regs->edi)); asm volatile ("mov %%gs, %0" : "=r" (regs->gs)); asm volatile ("mov %%fs, %0" : "=r" (regs->fs)); asm volatile ("mov %%es, %0" : "=r" (regs->es)); asm volatile ("mov %%ds, %0" : "=r" (regs->ds)); regs->eax = regs->ebx = regs->ecx = regs->edx = 0; regs->eip = (uint32)func; regs->useresp = t->StackUpperBase-0x4; regs->esp = t->StackUpperBase - 40; regs->ebp = t->Ebp = t->StackUpperBase; // 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->Esp = t->Ebp = 0; t->Next = NULL; TaskList = CurrentTask = t; }