feat: port gcc to MontaukOS

This commit is contained in:
daniel committed 2026-07-17 15:47:45 +02:00
1 parent 324b18edda
commit 8e6b619b02
14 files changed
+493 -19

No files matched your search

+42
View File
@@ -1103,6 +1103,48 @@ namespace Sched {
return &processTable[slot];
}
// Serializes stack growth so two threads faulting on the same page do not
// both map it (the loser's page would leak: FreeUserHalf only frees pages
// still referenced by the page tables).
static kcp::Spinlock stackGrowLock;
bool TryGrowUserStack(uint64_t faultAddr) {
constexpr uint64_t growBase = UserStackTop - UserStackMax;
constexpr uint64_t eagerBase = UserStackTop - UserStackSize;
if (faultAddr < growBase || faultAddr >= eagerBase) return false;
Process* proc = GetCurrentProcessPtr();
if (proc == nullptr) return false;
uint64_t pageVa = faultAddr & ~0xFFFULL;
stackGrowLock.Acquire();
// Another thread may have mapped this page between the fault and here.
if (Memory::VMM::Paging::IsUserRangeAccessible(proc->pml4Phys, pageVa, 0x1000, true)) {
stackGrowLock.Release();
return true;
}
void* page = Memory::g_pfa->AllocateZeroed();
if (page == nullptr) {
stackGrowLock.Release();
Kt::KernelLogStream(Kt::ERROR, "Sched")
<< "Out of memory growing user stack for pid " << proc->pid;
return false;
}
uint64_t physAddr = Memory::SubHHDM((uint64_t)page);
if (!Memory::VMM::Paging::MapUserIn(proc->pml4Phys, physAddr, pageVa)) {
stackGrowLock.Release();
Memory::g_pfa->Free(page);
return false;
}
stackGrowLock.Release();
asm volatile("invlpg (%0)" :: "r"(pageVa) : "memory");
return true;
}
void ExitProcess() {
auto* cpu = Smp::GetCurrentCpuData();
int slot = cpu->currentSlot;
+12 -1
View File
@@ -19,9 +19,14 @@ namespace Sched {
static constexpr int MaxProcesses = 256;
static constexpr uint64_t StackPages = 4; // 16 KiB kernel stack per thread
static constexpr uint64_t StackSize = StackPages * 0x1000;
static constexpr uint64_t UserStackPages = 8; // 32 KiB user stack (main thread)
static constexpr uint64_t UserStackPages = 8; // 32 KiB user stack (main thread, eagerly mapped)
static constexpr uint64_t UserStackSize = UserStackPages * 0x1000;
static constexpr uint64_t UserStackTop = 0x7FFFFFF000ULL; // Main-thread user stack top VA
// The main-thread stack demand-grows below the eager region up to this
// limit: page faults in [UserStackTop - UserStackMax, UserStackTop -
// UserStackSize) map fresh zeroed pages instead of killing the process.
// 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
static constexpr uint32_t UserReadDirSlots = 64; // rotating scratch pages for SYS_READDIR
static constexpr uint64_t UserReadDirBase =
@@ -139,6 +144,12 @@ namespace Sched {
// Get a pointer to the currently running thread's slot (may be a sibling).
Process* GetCurrentThreadPtr();
// Demand-grow the current process's main-thread user stack. Called from
// the page fault handler when a non-present fault lands in the stack
// growth region. Maps one zeroed page at the faulting address and returns
// true if the faulting instruction should be retried.
bool TryGrowUserStack(uint64_t faultAddr);
// Called by terminated processes to mark themselves done.
// Tears down the entire process (kills all sibling threads, frees address space).
void ExitProcess();