fix: kernel concurrency, interrupt context, and user VA safety
This commit is contained in:
1 parent
f222bf1f04
commit
b1c55073c7
71 files changed
+2654
-1092
No files matched your search
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user