refactor syscall ABI and FAT32 driver to use request structs and string views natively, enforce handle access rights on object lookup, add scheduler statistics tracking, fix KiSchedule to prevent 50% idle throttling on CPU-bound threads, better document x64 initial user stack alignment, fix process teardown to properly signal exit events and manage thread counts, optimize doom file I/O with a custom handle struct to internally track position and size, add SubsystemData to TEB for generic thread-local state, apply PAGE_NX to non-executable PE sections in the loader, update native apps, tests, and shells to match new APIs, update kernel32 directory retrieval.
This commit is contained in:
1 parent
603fbdfab1
commit
e1248f4afe
43 files changed
+2892
-1857
No files matched your search
@@ -20,10 +20,18 @@ static THREAD* gIdleThread;
|
||||
static THREAD* gOutgoingThread;
|
||||
static uint32_t gAgingCounter = 0;
|
||||
static volatile long gReschedulePending = 0;
|
||||
static KE_SCHED_STATS gSchedStats;
|
||||
|
||||
THREAD* KeGetCurrentThread(void) { return gCurrentThread; }
|
||||
void KeSetCurrentThread(THREAD* t) { gCurrentThread = t; }
|
||||
|
||||
void KeGetSchedulerStats(KE_SCHED_STATS* out) {
|
||||
if (!out) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSchedLock);
|
||||
*out = gSchedStats;
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
}
|
||||
|
||||
static void KiIdleLoop(void) {
|
||||
while (true) { __halt(); }
|
||||
}
|
||||
@@ -121,6 +129,14 @@ void KeUnreadyThread(THREAD* thread) {
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
}
|
||||
|
||||
static int KiAnyRunnableLocked(void) {
|
||||
for (int p = 0; p < PriorityCount; p++) {
|
||||
if (!LIST_IS_EMPTY(&gRunQueue[p]))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static THREAD* KiPickNext(void) {
|
||||
for (int p = PriorityCount - 1; p >= 0; p--) {
|
||||
if (!LIST_IS_EMPTY(&gRunQueue[p])) {
|
||||
@@ -149,7 +165,18 @@ static void KiSchedule(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSchedLock);
|
||||
cur->SchedLockFlags = flags;
|
||||
|
||||
// The currently running thread is not present in a run queue. If it is
|
||||
// still runnable and nobody else is ready, keep executing it. Otherwise a
|
||||
// lone CPU-bound thread gets alternated with the idle thread on every timer
|
||||
// tick, effectively turning a periodic preemption check into a 50% throttle.
|
||||
if (cur != gIdleThread && cur->State == ThreadRunning && !KiAnyRunnableLocked()) {
|
||||
gSchedStats.KeepCurrentDecisions++;
|
||||
KeReleaseSpinlock(&gSchedLock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
THREAD* next = KiPickNext();
|
||||
if (next == gIdleThread) gSchedStats.IdleSelections++;
|
||||
if (next == cur) {
|
||||
// Only re-queue if still running normally; a ThreadWaiting/ThreadDead
|
||||
// caller has already placed SchedulerLink elsewhere (or is discarding
|
||||
@@ -174,6 +201,7 @@ static void KiSchedule(void) {
|
||||
}
|
||||
|
||||
gOutgoingThread = cur;
|
||||
gSchedStats.ContextSwitches++;
|
||||
KeSwitchContext(cur, next);
|
||||
KeSchedulerPostSwitch();
|
||||
}
|
||||
@@ -190,12 +218,14 @@ void KeSchedulerTick(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSchedLock);
|
||||
cur->SchedLockFlags = flags; // Issue 5 fix
|
||||
|
||||
gSchedStats.Ticks++;
|
||||
cur->QuantaConsumed++;
|
||||
|
||||
if (cur != gIdleThread && cur->QuantaConsumed >= DEMOTION_QUANTA) {
|
||||
cur->QuantaConsumed = 0;
|
||||
if (cur->Priority > PriorityLow) {
|
||||
cur->Priority = (THREAD_PRIORITY)(cur->Priority - 1);
|
||||
gSchedStats.Demotions++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +238,7 @@ void KeSchedulerTick(void) {
|
||||
LIST_ENTRY* node = ListPopHead(&gRunQueue[p]);
|
||||
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
t->Priority = PriorityHigh;
|
||||
gSchedStats.AgingPromotions++;
|
||||
ListInsertTail(&gRunQueue[PriorityHigh], &t->SchedulerLink);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user