luxos/Kernel/tasking/tasking-multi.c

108 lines
2.2 KiB
C

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