luxos/Kernel/tasking/tasking-multi.c

142 lines
2.9 KiB
C

/*
* tasking-multi.c
*
* Created on: Sep 7, 2011
* Author: Tiberiu
*/
#include <tasking.h>
#include <debugio.h>
#include <stdio.h>
volatile Task *CurrentTask;
volatile Task *TaskQueue;
volatile uint32 NextPid = 1;
void TaskingInitialize()
{
// Stop interrupts
asm volatile ("cli");
// Relocate stack
TaskingMoveStack(0xE0000000, 0x4000);
// Set up first task (kernel)
CurrentTask = TaskQueue = (Task*) kmalloc(sizeof(Task));
CurrentTask->Pid = NextPid ++;
CurrentTask->Esp = CurrentTask->Ebp = CurrentTask->Eip = 0;
CurrentTask->Pd = CurrentDirectory;
CurrentTask->Next = NULL;
// Reenable interrupts
asm volatile ("sti");
Log("Tasking", "Initialized, currenttask: pid=%u esp=%x ebp=%x eip=%x Pd=%x Next=%x\n", CurrentTask->Pid,
CurrentTask->Esp, CurrentTask->Ebp, CurrentTask->Eip, CurrentTask->Pd, CurrentTask->Next);
}
int32 Fork()
{
asm volatile ("cli");
Task* Parent = (Task*) CurrentTask;
PageDirectory* Dir = PagingCloneDirectory(CurrentDirectory);
// Create a new process
Task* n = (Task*)kmalloc(sizeof(Task));
n->Pid = NextPid++;
n->Esp = n->Ebp = 0;
n->Eip = 0;
n->Pd = Dir;
n->Next = 0;
// Add it at the end of the queue
Task* temp = (Task*) TaskQueue;
while (temp->Next) temp = temp->Next; // Find end of queue
temp->Next = n; // Add it
// Read eip
uint32 eip = TaskingReadEip();
// We could be the parent
if (CurrentTask == Parent)
{
uint32 esp, ebp;
asm volatile ("mov %%esp, %0" : "=r"(esp));
asm volatile ("mov %%ebp, %0" : "=r"(ebp));
n->Esp = esp;
n->Ebp = ebp;
n->Eip = eip;
asm volatile ("sti");
return n->Pid;
}
// Or the child
else return 0;
}
void TaskingScheduler()
{
// For now, just switch tasks
TaskingSwitch();
}
void Func()
{
}
void TaskingSwitch()
{
// Make sure tasking is initialized, or there are at least 2 processes running
if (!CurrentTask) return;
// Save esp & epb
uint32 esp, ebp, eip;
asm volatile("mov %%esp, %0" : "=r"(esp));
asm volatile("mov %%ebp, %0" : "=r"(ebp));
eip = TaskingReadEip();
// Have we just switched tasks?
if (eip == 0xABCDE) return;
// No? Switch
// Save stack address and current instruction pointer
CurrentTask->Eip = eip;
CurrentTask->Esp = esp;
CurrentTask->Ebp = ebp;
//Log("Tasking", "Saved eip=%x esp=%x ebp=%x\n", eip, esp, ebp);
CurrentTask = CurrentTask ->Next; // Switch task
if (!CurrentTask) CurrentTask = TaskQueue; // End of queue? Start over
// Read registers
eip = CurrentTask->Eip;
esp = CurrentTask->Esp;
ebp = CurrentTask->Ebp;
//Log("Tasking", "Loaded eip=%x esp=%x ebp=%x", eip, esp, ebp);
CurrentDirectory = CurrentTask->Pd;
MagicBreakpoint();
// Put data in registers
asm volatile (" "
"cli;"
"mov %0, %%ecx;"
"mov %1, %%esp;"
"mov %2, %%ebp;"
"mov %3, %%cr3;"
"mov $0xABCDE, %%eax;"
"sti;"
"jmp *%%ecx"
: : "r"(eip), "r"(esp), "r"(ebp), "r"(CurrentDirectory->PhysicalAddr));
}
int32 GetPid()
{
return CurrentTask->Pid;
}