feat(scheduler): working scheduler

This commit is contained in:
karina
2026-04-29 17:00:11 +04:00
parent 3f51d93a4e
commit e06abbcb23
12 changed files with 220 additions and 17 deletions
+2 -2
View File
@@ -4,8 +4,8 @@
#include <IO/Serial.h>
#include <OS/Panic.h>
void ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) {
if (type == ExceptionsIRQEl1h || type == ExceptionsIRQEl064) return GICDispatch(type);
Address ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) {
if (type == ExceptionsIRQEl1h || type == ExceptionsIRQEl064) return GICDispatch(frame, type);
OSPanicException(frame);
}
+8 -4
View File
@@ -52,14 +52,18 @@ void GICCWriteEOIR(UInt32 irqID) {
GICC[kGICCEOIR / 4] = irqID;
}
void GICDispatch(ExceptionsType type) {
if (type != ExceptionsIRQEl1h && type != ExceptionsIRQEl064) return;
Address GICDispatch(ExceptionsContext* frame, ExceptionsType type) {
if (type != ExceptionsIRQEl1h && type != ExceptionsIRQEl064) return (Address)frame;
UInt32 irqID = GICCReadIAR() & 0x3FF;
if (irqID == 1023) return; // spurious interrupt
if (irqID == 1023) return (Address)frame; // spurious interrupt
Address newStackPointer = (Address)frame;
if (irqID == kTimerIRQ) {
TimerReset(kTimerFrequency);
newStackPointer = TimerHandler(frame);
}
GICCWriteEOIR(irqID);
return newStackPointer;
}
+14
View File
@@ -1,5 +1,9 @@
#include <Arch/Timer.h>
#include <Arch/GIC.h>
#include <OS/Scheduler.h>
#include <Arch/Exceptions.h>
static volatile UInt64 sTimerCounter = 0;
void TimerInitialize() {
GICEnableInterrupt(kTimerIRQ);
@@ -12,3 +16,13 @@ void TimerReset(UInt64 interval) {
__asm__ volatile ("msr cntv_tval_el0, %0" :: "r"(frequency /interval));
__asm__ volatile ("msr cntv_ctl_el0, %0" :: "r"((UInt64)1));
}
Address TimerHandler(ExceptionsContext* frame) {
sTimerCounter++;
TimerReset(kTimerFrequency);
return SchedulerNext((Address)frame);
}
UInt64 TimerGetCounter() {
return sTimerCounter;
}
+7 -2
View File
@@ -1,6 +1,6 @@
.macro ventry type
.align 7
sub sp, sp, #272 // save 272 bytes of stack
sub sp, sp, #288 // save 288 bytes of stack
stp x0, x1, [sp, #0] // move stack
mov x1, #\type // move type to x1
b ExceptionsTrapEntry
@@ -50,12 +50,17 @@ ExceptionsTrapEntry:
mrs x21, elr_el1
mrs x22, spsr_el1
mrs x23, esr_el1
mrs x24, sp_el0
stp x30, x21, [sp, #16 * 15]
stp x22, x23, [sp, #16 * 16]
mov x0, sp
bl ExceptionsHandler
mov sp, x0
ldp x24, xzr, [sp, #16 * 17]
msr sp_el0, x24
ldp x22, x23, [sp, #16 * 16]
msr spsr_el1, x22
@@ -79,7 +84,7 @@ ExceptionsTrapEntry:
ldp x2, x3, [sp, #16 * 1]
ldp x0, x1, [sp, #0]
add sp, sp, #272
add sp, sp, #288
eret
.global ExceptionsVectorsInit
+4
View File
@@ -8,6 +8,7 @@
#include <VM/Heap.h>
#include <OS/Log.h>
#include <OS/Panic.h>
#include <OS/Scheduler.h>
void KernelMain(Bootinfo* bootinfo) {
OSLog("Kernel started.\n");
@@ -16,6 +17,7 @@ void KernelMain(Bootinfo* bootinfo) {
}
VMBootMemoryMap bootMap = {0};
bootMap.reservedCount = 0;
DTBParse(bootinfo->dtb, &bootMap);
@@ -30,5 +32,7 @@ void KernelMain(Bootinfo* bootinfo) {
TimerInitialize();
CPUEnableInterrupts();
SchedulerInitialize();
OSLog("Kernel initialized.\n");
}
+7 -7
View File
@@ -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();
+116
View File
@@ -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);
}