fix: kernel concurrency, interrupt context, and user VA safety

This commit is contained in:
daniel committed 2026-08-01 15:43:38 +02:00
1 parent f222bf1f04
commit b1c55073c7
71 files changed
+2654 -1092

No files matched your search

+38 -4
View File
@@ -6,6 +6,7 @@
#pragma once
#include <cstdint>
#include <atomic>
#include <Api/Syscall.hpp>
namespace Sched {
@@ -28,6 +29,24 @@ namespace Sched {
// Heavy recursive programs (GCC's cc1plus) need megabytes of stack.
static constexpr uint64_t UserStackMax = 64 * 1024 * 1024; // 64 MiB
static constexpr uint64_t UserHeapBase = 0x40000000ULL; // User heap start VA
// Keep the bump-allocated heap below the fixed shared-library range. A
// failed bound check is recoverable (SYS_ALLOC returns null); allowing the
// heap to cross this boundary would silently replace library PTEs.
static constexpr uint64_t UserHeapLimit = 0x60000000ULL;
// Surface mappings use reusable, fixed-size per-process slots instead of
// consuming heap VA forever. 64 * 32 MiB occupies [0x7000000000,
// 0x7080000000), comfortably below the main user stack.
static constexpr uint64_t UserSurfaceBase = 0x7000000000ULL;
static constexpr uint64_t UserSurfaceSlotSize = 32ULL * 1024 * 1024;
static constexpr uint64_t UserSurfaceSlots = 64;
static constexpr uint64_t UserSurfaceEnd =
UserSurfaceBase + UserSurfaceSlots * UserSurfaceSlotSize;
// The two write-combined scanout mappings live in their own region.
static constexpr uint64_t UserFramebufferBase = 0x7100000000ULL;
static constexpr uint64_t UserFramebufferLimit = 0x7140000000ULL;
static_assert(UserHeapBase < UserHeapLimit);
static_assert(UserSurfaceEnd <= UserFramebufferBase);
static_assert(UserFramebufferLimit < UserStackTop - UserStackMax);
static constexpr uint32_t UserReadDirSlots = 64; // rotating scratch pages for SYS_READDIR
static constexpr uint64_t UserReadDirBase =
UserHeapBase - (uint64_t)UserReadDirSlots * 0x1000ULL;
@@ -74,7 +93,7 @@ namespace Sched {
uint64_t tlsAlign = 0;
int runningOnCpu; // CPU index running this process (-1 if not running)
bool killPending = false; // Set by Sys_Kill when target is running on another CPU
std::atomic<bool> killPending{false}; // Cross-CPU kill handoff
bool reapReady = false; // Set once teardown is complete and BSP may free slot resources
bool startPending = false; // Spawned but not yet made runnable
@@ -124,9 +143,13 @@ namespace Sched {
// True when there is runnable work somewhere in the process table.
bool HasReadyProcesses();
// Ask the current CPU to yield once to its idle kernel context on the next
// scheduler pass so deferred device work cannot starve under full load.
void RequestKernelWork();
// Called from the APIC timer handler with the elapsed time for that CPU's
// tick interval. The BSP runs at 1 ms; APs may use a coarser interval.
void Tick(uint32_t elapsedMs = 1);
void Tick(uint32_t elapsedMs = 1, bool interruptedUser = false);
// Get the PID of the currently running process (-1 if idle).
// For sibling threads this returns the primary slot's PID -- i.e. the
@@ -164,6 +187,11 @@ namespace Sched {
// out of the user heap. Returns the new TID, or -1 on failure.
int SpawnThread(uint64_t entry, uint64_t arg, uint64_t userStackTop);
// Reserve a page-aligned range from a process's shared bump heap. The
// reservation is serialized across sibling threads and bounded below the
// fixed shared-library mappings.
bool ReserveUserHeapRange(int primarySlot, uint64_t size, uint64_t& outVa);
// Terminate the currently executing thread. If this is the main thread,
// the entire process exits (equivalent to ExitProcess).
[[noreturn]] void ExitCurrentThread(int exitCode);
@@ -194,8 +222,14 @@ namespace Sched {
bool BlockOnObjectIf(void* object, uint64_t timeoutMs,
bool (*shouldBlock)(void*), void* context);
// BSP-only scheduler housekeeping: wake expired sleepers and reclaim
// terminated process resources.
// Take this token before testing an object's ready condition, then pass it
// to BlockOnObjectSince. A wake between the test and scheduler enrollment
// makes the latter return without blocking instead of losing the edge.
uint64_t ObserveObjectWake(void* object);
bool BlockOnObjectSince(void* object, uint64_t timeoutMs, uint64_t observedWake);
// BSP idle-context housekeeping: reclaim terminated process resources and
// run policy work previously queued by the timer or process teardown.
void RunBspMaintenance();
// Return the earliest blocked sleep/object timeout deadline in ticks,