luxos/Kernel/tasking/tasking-multi.c

104 lines
2.6 KiB
C

/*
* tasking-multi.c
*
* Created on: Sep 8, 2011
* Author: Tiberiu
*/
#include <tasking.h>
#include <memory-add.h>
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;
}