feat: overhaul userspace heap and virtual memory
This commit is contained in:
1 parent
4ecec32c5c
commit
9b23d99082
21 files changed
+905
-451
No files matched your search
@@ -493,6 +493,8 @@ namespace Sched {
|
||||
proc.kernelStackTop = kernelStackTop;
|
||||
proc.userStackTop = UserStackTop - 8;
|
||||
proc.heapNext = UserHeapBase;
|
||||
for (uint64_t i = 0; i < UserHeapBitmapWords; i++)
|
||||
g_userHeapPageMap[slot][i] = 0;
|
||||
proc.fsBase = tls.fsBase;
|
||||
proc.tlsTemplateVaddr = tls.templateVaddr;
|
||||
proc.tlsFileSize = tls.fileSize;
|
||||
@@ -651,6 +653,7 @@ namespace Sched {
|
||||
}
|
||||
if (!ok) {
|
||||
Ipc::UnmapAndFreeUserRange(sharedPml4, base, mappedPages);
|
||||
ReleaseUserHeapRange(primarySlot_, base, numPages * 0x1000ULL);
|
||||
Kt::KernelLogStream(Kt::ERROR, "Sched")
|
||||
<< "Thread TLS allocation failed";
|
||||
return -1;
|
||||
@@ -675,8 +678,11 @@ namespace Sched {
|
||||
// Allocate kernel stack.
|
||||
void* stackMem = Memory::g_pfa->ReallocConsecutive(nullptr, StackPages);
|
||||
if (stackMem == nullptr) {
|
||||
if (threadTlsPages != 0)
|
||||
if (threadTlsPages != 0) {
|
||||
Ipc::UnmapAndFreeUserRange(sharedPml4, threadTlsBase, threadTlsPages);
|
||||
ReleaseUserHeapRange(primarySlot_, threadTlsBase,
|
||||
threadTlsPages * 0x1000ULL);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
memset(stackMem, 0, StackSize);
|
||||
@@ -698,8 +704,11 @@ namespace Sched {
|
||||
if (slot < 0) {
|
||||
schedLock.Release();
|
||||
Memory::g_pfa->Free(stackMem, StackPages);
|
||||
if (threadTlsPages != 0)
|
||||
if (threadTlsPages != 0) {
|
||||
Ipc::UnmapAndFreeUserRange(sharedPml4, threadTlsBase, threadTlsPages);
|
||||
ReleaseUserHeapRange(primarySlot_, threadTlsBase,
|
||||
threadTlsPages * 0x1000ULL);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -774,20 +783,54 @@ namespace Sched {
|
||||
|
||||
schedLock.Acquire();
|
||||
Process& primary = processTable[primarySlot_];
|
||||
uint64_t base = primary.heapNext;
|
||||
bool validOwner = primary.primarySlot == primarySlot_ &&
|
||||
primary.state != ProcessState::Free &&
|
||||
primary.state != ProcessState::Terminated;
|
||||
bool fits = validOwner && base >= UserHeapBase &&
|
||||
base <= UserHeapLimit && size <= UserHeapLimit - base;
|
||||
if (fits) {
|
||||
primary.heapNext = base + size;
|
||||
outVa = base;
|
||||
bool fits = false;
|
||||
uint64_t pages = size / 0x1000ULL;
|
||||
uint64_t runStart = 0;
|
||||
uint64_t runLength = 0;
|
||||
|
||||
if (validOwner && pages <= UserHeapPages) {
|
||||
for (uint64_t page = 0; page < UserHeapPages; page++) {
|
||||
bool used = (g_userHeapPageMap[primarySlot_][page / 64]
|
||||
& (1ULL << (page % 64))) != 0;
|
||||
if (used) {
|
||||
runLength = 0;
|
||||
continue;
|
||||
}
|
||||
if (runLength == 0) runStart = page;
|
||||
runLength++;
|
||||
if (runLength == pages) {
|
||||
for (uint64_t p = runStart; p < runStart + pages; p++)
|
||||
g_userHeapPageMap[primarySlot_][p / 64] |= 1ULL << (p % 64);
|
||||
outVa = UserHeapBase + runStart * 0x1000ULL;
|
||||
uint64_t end = outVa + size;
|
||||
if (end > primary.heapNext) primary.heapNext = end;
|
||||
fits = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
schedLock.Release();
|
||||
return fits;
|
||||
}
|
||||
|
||||
void ReleaseUserHeapRange(int primarySlot_, uint64_t va, uint64_t size) {
|
||||
if (primarySlot_ < 0 || primarySlot_ >= MaxProcesses || size == 0 ||
|
||||
(va & 0xFFFULL) != 0 || (size & 0xFFFULL) != 0 ||
|
||||
va < UserHeapBase || va > UserHeapLimit || size > UserHeapLimit - va) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t first = (va - UserHeapBase) / 0x1000ULL;
|
||||
uint64_t pages = size / 0x1000ULL;
|
||||
schedLock.Acquire();
|
||||
for (uint64_t p = first; p < first + pages; p++)
|
||||
g_userHeapPageMap[primarySlot_][p / 64] &= ~(1ULL << (p % 64));
|
||||
schedLock.Release();
|
||||
}
|
||||
|
||||
static void FreeSiblingThreadTls(Process& thr) {
|
||||
int primarySlot_ = thr.primarySlot;
|
||||
if (primarySlot_ < 0 || primarySlot_ >= MaxProcesses ||
|
||||
@@ -811,6 +854,7 @@ namespace Sched {
|
||||
uint64_t pages = (blockSize + 16 + 0xFFF) / 0x1000;
|
||||
thr.fsBase = 0;
|
||||
Ipc::UnmapAndFreeUserRange(primary.pml4Phys, base, pages);
|
||||
ReleaseUserHeapRange(primarySlot_, base, pages * 0x1000ULL);
|
||||
}
|
||||
|
||||
// Switch away from a slot we have just marked non-runnable while holding
|
||||
|
||||
Reference in new issue
Block a user