feat: further kernel power and power optimizations

This commit is contained in:
2026-04-21 20:51:12 +02:00
parent d1fffecff6
commit 0dfb3e8dbb
31 changed files with 895 additions and 52 deletions
+84
View File
@@ -14,6 +14,7 @@
#include <CppLib/Stream.hpp>
#include <CppLib/Spinlock.hpp>
#include <Hal/Apic/Apic.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/GDT.hpp>
#include <Hal/SmpBoot.hpp>
#include <Timekeeping/ApicTimer.hpp>
@@ -50,6 +51,41 @@ namespace Sched {
return (uint64_t)Memory::VMM::g_paging->PML4;
}
static void RescheduleIpiHandler(uint8_t) {
auto* cpu = Smp::GetCurrentCpuData();
if (cpu == nullptr || cpu->currentSlot >= 0 || readyCount <= 0) {
return;
}
Schedule();
}
static void KickOneIdleCpu(int sourceCpuIndex) {
if (readyCount <= 0) {
return;
}
auto tryKick = [&](Smp::CpuData* target) {
if (target == nullptr || !target->started) return false;
if (target->cpuIndex == sourceCpuIndex) return false;
if (target->currentSlot >= 0) return false;
Hal::LocalApic::SendFixedIpi(target->lapicId,
Hal::IRQ_VECTOR_BASE + Hal::IRQ_RESCHEDULE);
return true;
};
if (tryKick(Smp::GetCpuData(0))) {
return;
}
for (int i = 0; i < Smp::GetCpuCount(); i++) {
if (tryKick(Smp::GetCpuData(i))) {
return;
}
}
}
static void SwitchAwayFromBlockedCurrentLocked() {
auto* cpu = Smp::GetCurrentCpuData();
int slot = cpu->currentSlot;
@@ -160,6 +196,7 @@ namespace Sched {
}
nextPid = 0;
Hal::RegisterIrqHandler(Hal::IRQ_RESCHEDULE, RescheduleIpiHandler);
Kt::KernelLogStream(Kt::OK, "Sched") << "Initialized (" << MaxProcesses
<< " process slots, " << (uint64_t)TimeSliceMs << " ms time slice)";
@@ -398,6 +435,7 @@ namespace Sched {
int resultPid = proc.pid;
schedLock.Release();
KickOneIdleCpu(Smp::GetCurrentCpuData() ? Smp::GetCurrentCpuData()->cpuIndex : -1);
return resultPid;
}
@@ -448,6 +486,8 @@ namespace Sched {
}
void RunBspMaintenance() {
bool wokeProcesses = false;
schedLock.Acquire();
uint64_t now = Timekeeping::GetTicks();
for (int i = 0; i < MaxProcesses; i++) {
@@ -459,10 +499,15 @@ namespace Sched {
processTable[i].waitingOnObject = nullptr;
processTable[i].state = ProcessState::Ready;
readyCount++;
wokeProcesses = true;
}
}
schedLock.Release();
if (wokeProcesses) {
KickOneIdleCpu(0);
}
ReclaimTerminated();
}
@@ -704,6 +749,10 @@ namespace Sched {
processTable[next].runningOnCpu = cpu->cpuIndex;
processTable[next].sliceRemaining = TimeSliceMs;
if (readyCount > 0) {
KickOneIdleCpu(cpu->cpuIndex);
}
uint64_t newCR3 = processTable[next].pml4Phys;
cpu->kernelRsp = processTable[next].kernelStackTop;
cpu->tss->rsp0 = processTable[next].kernelStackTop;
@@ -789,6 +838,7 @@ namespace Sched {
}
schedLock.Release();
KickOneIdleCpu(Smp::GetCurrentCpuData() ? Smp::GetCurrentCpuData()->cpuIndex : -1);
// Safe to clean up resources now -- process is not running anywhere.
WinServer::CleanupProcess(killedPid);
@@ -898,9 +948,38 @@ namespace Sched {
SwitchAwayFromBlockedCurrentLocked();
}
bool BlockOnObjectIf(void* object, uint64_t timeoutMs,
bool (*shouldBlock)(void*), void* context) {
if (object == nullptr || shouldBlock == nullptr) return false;
auto* cpu = Smp::GetCurrentCpuData();
if (cpu == nullptr) return false;
int slot = cpu->currentSlot;
if (slot < 0) return false;
schedLock.Acquire();
if (!shouldBlock(context)) {
schedLock.Release();
return false;
}
processTable[slot].state = ProcessState::Blocked;
processTable[slot].waitingForPid = -1;
processTable[slot].waitingOnObject = object;
processTable[slot].sleepUntilTick = (timeoutMs > 0)
? (Timekeeping::GetTicks() + timeoutMs)
: 0;
processTable[slot].runningOnCpu = -1;
SwitchAwayFromBlockedCurrentLocked();
return true;
}
void WakeObjectWaiters(void* object) {
if (object == nullptr) return;
bool wokeAny = false;
schedLock.Acquire();
for (int i = 0; i < MaxProcesses; i++) {
if (processTable[i].state != ProcessState::Blocked) continue;
@@ -911,8 +990,13 @@ namespace Sched {
processTable[i].waitingForPid = -1;
processTable[i].state = ProcessState::Ready;
readyCount++;
wokeAny = true;
}
schedLock.Release();
if (wokeAny) {
KickOneIdleCpu(Smp::GetCurrentCpuData() ? Smp::GetCurrentCpuData()->cpuIndex : -1);
}
}
bool IsAlive(int pid) {