feat(scheduler): working scheduler
This commit is contained in:
@@ -93,11 +93,11 @@ __attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) {
|
||||
PrintSeparator();
|
||||
OSLog("Registers:\n");
|
||||
PrintSeparator();
|
||||
OSLog("x0 = 0x%X; x1 = 0x%X\n", frame->x0, frame->x1);
|
||||
OSLog("x2 = 0x%X; x3 = 0x%X\n", frame->x2, frame->x3);
|
||||
OSLog("x4 = 0x%X; x5 = 0x%X\n", frame->x4, frame->x5);
|
||||
OSLog("x6 = 0x%X; x7 = 0x%X\n", frame->x6, frame->x7);
|
||||
OSLog("x8 = 0x%X; x9 = 0x%X\n", frame->x8, frame->x9);
|
||||
OSLog("x0 = 0x%X; x1 = 0x%X\n", frame->x0, frame->x1);
|
||||
OSLog("x2 = 0x%X; x3 = 0x%X\n", frame->x2, frame->x3);
|
||||
OSLog("x4 = 0x%X; x5 = 0x%X\n", frame->x4, frame->x5);
|
||||
OSLog("x6 = 0x%X; x7 = 0x%X\n", frame->x6, frame->x7);
|
||||
OSLog("x8 = 0x%X; x9 = 0x%X\n", frame->x8, frame->x9);
|
||||
OSLog("x10 = 0x%X; x11 = 0x%X\n", frame->x10, frame->x11);
|
||||
OSLog("x12 = 0x%X; x13 = 0x%X\n", frame->x12, frame->x13);
|
||||
OSLog("x14 = 0x%X; x15 = 0x%X\n", frame->x14, frame->x15);
|
||||
@@ -107,8 +107,8 @@ __attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) {
|
||||
OSLog("x22 = 0x%X; x23 = 0x%X\n", frame->x22, frame->x23);
|
||||
OSLog("x24 = 0x%X; x25 = 0x%X\n", frame->x24, frame->x25);
|
||||
OSLog("x26 = 0x%X; x27 = 0x%X\n", frame->x26, frame->x27);
|
||||
OSLog("\t\tx28 = 0x%X\n", frame->x28);
|
||||
OSLog("FP = 0x%X; LR = 0x%X\n", frame->x29, frame->x30);
|
||||
OSLog("\t x28 = 0x%X\n", frame->x28);
|
||||
OSLog("FP = 0x%X; LR = 0x%X\n", frame->x29, frame->x30);
|
||||
|
||||
DrawPanicFooter();
|
||||
Halt();
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#include <OS/Scheduler.h>
|
||||
#include <OS/Panic.h>
|
||||
#include <Arch/Exceptions.h>
|
||||
#include <Arch/CPU.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <VM/Heap.h>
|
||||
#include <Lib/Align.h>
|
||||
#include <Lib/String.h>
|
||||
|
||||
OSTask* gOSSchedulerCurrentTask = nullptr;
|
||||
UInt32 gOSSchedulerNextProcessID = 1;
|
||||
|
||||
static OSProcess sOSSchedulerKernelProcess;
|
||||
|
||||
void SchedulerInitialize() {
|
||||
sOSSchedulerKernelProcess.id = 0;
|
||||
sOSSchedulerKernelProcess.state = OSTaskStateRunning;
|
||||
sOSSchedulerKernelProcess.l0Table = gVMKernelL0Table;
|
||||
StringCopy(sOSSchedulerKernelProcess.name, "kernel");
|
||||
|
||||
OSTask* kernelTask = (OSTask*)HeapAllocate(sizeof(OSTask));
|
||||
if (!kernelTask) OSPanic("Failed to allocate kernel task");
|
||||
|
||||
MemorySet(kernelTask, 0, sizeof(OSTask));
|
||||
kernelTask->id = 0;
|
||||
kernelTask->process = &sOSSchedulerKernelProcess;
|
||||
kernelTask->sleepTicks = 0;
|
||||
kernelTask->next = kernelTask;
|
||||
kernelTask->state = OSTaskStateRunning;
|
||||
kernelTask->waitingForProcessId = -1;
|
||||
|
||||
gOSSchedulerCurrentTask = kernelTask;
|
||||
}
|
||||
|
||||
OSTask* SchedulerSpawn(void(*entryPoint)(), OSProcess* owner, Boolean isUser, Address fixedUserStackAddress) {
|
||||
OSTask* task = (OSTask*)HeapAllocate(sizeof(OSTask));
|
||||
Pointer stackBase = nullptr;
|
||||
if (!task) goto cleanup;
|
||||
|
||||
if (!owner) owner = &sOSSchedulerKernelProcess;
|
||||
Size stackSize = kOSSchedulerTaskStackSize;
|
||||
stackBase = HeapAllocate(stackSize);
|
||||
if (!stackBase) goto cleanup;
|
||||
|
||||
Address stackPointer = (Address)stackBase + stackSize;
|
||||
stackPointer -= sizeof(ExceptionsContext);
|
||||
stackPointer = AlignDown64(stackPointer, 16);
|
||||
ExceptionsContext* context = (ExceptionsContext*)stackPointer;
|
||||
MemorySet(context, 0, sizeof(ExceptionsContext));
|
||||
context->elr_el1 = (Address)entryPoint;
|
||||
|
||||
if (isUser) {
|
||||
context->spsr_el1 = 0x00000000; // El0t (M[3:0] = 0b0000) allow interrupts
|
||||
context->sp_el0 = fixedUserStackAddress;
|
||||
} else {
|
||||
context->spsr_el1 = 0x00000005; // El1h (M[3:0] = 0b0101) allow interrupts
|
||||
}
|
||||
|
||||
task->stackPointer = stackPointer;
|
||||
task->process = owner;
|
||||
task->id = owner->id;
|
||||
task->sleepTicks = 0;
|
||||
task->kernelStackBase = stackBase;
|
||||
task->kernelStackTop = (Address)stackBase + stackSize;
|
||||
task->state = OSTaskStateRunning;
|
||||
task->waitingForProcessId = -1;
|
||||
|
||||
task->next = gOSSchedulerCurrentTask->next;
|
||||
gOSSchedulerCurrentTask->next = task;
|
||||
|
||||
return task;
|
||||
cleanup:
|
||||
if (task) HeapFree(task);
|
||||
if (stackBase) HeapFree(stackBase);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Address SchedulerNext(Address stackPointer) {
|
||||
if (!gOSSchedulerCurrentTask) return stackPointer;
|
||||
|
||||
gOSSchedulerCurrentTask->stackPointer = stackPointer;
|
||||
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
|
||||
|
||||
do {
|
||||
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
|
||||
taskIterator = taskIterator->next;
|
||||
} while (taskIterator != gOSSchedulerCurrentTask->next);
|
||||
|
||||
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
|
||||
|
||||
OSTask* nextTask = gOSSchedulerCurrentTask->next;
|
||||
loop {
|
||||
if (nextTask->state == OSTaskStateSleeping && nextTask->sleepTicks == 0) nextTask->state = OSTaskStateRunning;
|
||||
if (nextTask->state == OSTaskStateRunning) break;
|
||||
nextTask = nextTask->next;
|
||||
|
||||
if (nextTask == gOSSchedulerCurrentTask) {
|
||||
if (gOSSchedulerCurrentTask->state == OSTaskStateRunning) break;
|
||||
OSPanic("No running tasks");
|
||||
}
|
||||
}
|
||||
|
||||
if (nextTask->process->l0Table != gOSSchedulerCurrentTask->process->l0Table) {
|
||||
Address physicalL0Table = VMHHDMToPhys((Address)nextTask->process->l0Table);
|
||||
CPUSwitchAddressSpace(physicalL0Table);
|
||||
}
|
||||
gOSSchedulerCurrentTask = nextTask;
|
||||
|
||||
return gOSSchedulerCurrentTask->stackPointer;
|
||||
}
|
||||
|
||||
void SchedulerYield(UInt64 ticks) {
|
||||
gOSSchedulerCurrentTask->sleepTicks = ticks;
|
||||
gOSSchedulerCurrentTask->state = OSTaskStateSleeping;
|
||||
CPUException(kOSSchedulerExceptionNumber);
|
||||
}
|
||||
Reference in New Issue
Block a user