redo boot around an explicit system volume and fixed kernel/HAL images, redo volumes and filesystem paths around capabilities instead of drive numbers and kernel CWD state, add a capability/security model with derived and revocable handles and security contexts, add port IPC and rssrv to manage the userspace resource namespace and publish the system volume, move process, dll and path loading to userspace and add process builder syscalls, init now supervises rssrv and the session process, redo the syscall ABI around request structs and four arguments, add a volume manager and proper partition arrival/removal handling so FAT and NTFS mount dynamically, clean up the HAL/DDK boundary so drivers don't depend on HAL internals, save fpu state properly now, the serial driver doesn't hang on a missing port, fix AHCI startup races, fix timeout accounting, fix shared mmap writeback, more smoke tests
This commit is contained in:
1 parent
4add6789ba
commit
f882d339fb
232 files changed
+20934
-8898
No files matched your search
+49
-40
@@ -3,10 +3,13 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <intrin.h>
|
||||
#include <kernel/ke_idt.h>
|
||||
#include <kernel/ke_hal.h>
|
||||
#include <kernel/ke_sched.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <kernel/ke_thread.h>
|
||||
#include <kernel/se_security.h>
|
||||
#include <kernel/ke_mutex.h>
|
||||
#include <kernel/ke_spinlock.h>
|
||||
#include <kernel/ke_irql.h>
|
||||
@@ -18,7 +21,6 @@
|
||||
#include <kernel/ke_list.h>
|
||||
#include <kernel/ke_work.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <kernel/hal/hal_apic.h>
|
||||
|
||||
static LIST_ENTRY gNormalRunQueue[PriorityCount];
|
||||
static LIST_ENTRY gRealtimeRunQueue[KE_REALTIME_PRIORITY_COUNT];
|
||||
@@ -129,7 +131,7 @@ int KiSchedulerRefreshMutexDonation(MUTEX* mutex) {
|
||||
|
||||
// Implements the default Thread Affinity Mask operation.
|
||||
static uint64_t KiDefaultThreadAffinityMask(void) {
|
||||
// Normal kernel, user, and driver-created threads are BSP-affine by
|
||||
// Normal kernel, user, and driver-created threads are boot-processor-affine by
|
||||
// default. Code that is explicitly audited for AP execution can widen its
|
||||
// affinity before the thread enters the ready queue.
|
||||
return 1ULL;
|
||||
@@ -200,7 +202,7 @@ static void KiRequestRescheduleCpuLocked(KCPU* target) {
|
||||
|
||||
KCPU* self = KeGetCurrentCpu();
|
||||
if (self && target->CpuIndex != self->CpuIndex) {
|
||||
HalApicSendRescheduleIpi(target->LapicId);
|
||||
KeSendProcessorInterrupt(target->HardwareId, KE_VECTOR_RESCHEDULE_IPI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,8 +709,8 @@ static void KiIdleLoop(void) {
|
||||
KCPU* cpu = KeGetCurrentCpu();
|
||||
cpu->SchedulerTicks++;
|
||||
|
||||
// AP idle threads sleep until an interrupt or reschedule IPI wakes the
|
||||
// CPU. Ready paths set ReschedulePending and target the CPU's LAPIC;
|
||||
// Secondary-processor idle threads sleep until an interrupt or reschedule IPI wakes
|
||||
// the CPU. Ready paths set ReschedulePending and target that processor;
|
||||
// KiExitInterrupt consumes the request after EOI.
|
||||
if (KiAnyRunnableForCurrentCpu()) {
|
||||
KeYield();
|
||||
@@ -719,7 +721,7 @@ static void KiIdleLoop(void) {
|
||||
// the idle thread through an unusual switch path must not sleep with
|
||||
// interrupts disabled, otherwise reschedule/TLB shootdown IPIs can
|
||||
// be delayed forever.
|
||||
HalWaitForInterrupt();
|
||||
KeWaitForInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,7 +733,7 @@ void KiInitializeSchedulerGlobal(void) {
|
||||
KeInitializeWorkItem(&gTimeoutWorkItem, KiTimeoutWorkRoutine, (void*)0);
|
||||
gSchedLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
KSTATUS s = KeCreateProcess("idle", &gIdleProcess);
|
||||
KSTATUS s = KeCreateProcess("idle", SeGetRootSecurityContext(), &gIdleProcess);
|
||||
if (!KSUCCESS(s))
|
||||
KePanic(KE_PANIC_CODE_INIT, "scheduler: failed to create idle process, status=%u\n", s);
|
||||
gIdleProcess->Flags |= KE_PROCESS_FLAG_IDLE | KE_PROCESS_FLAG_TERMINATION_PROTECTED;
|
||||
@@ -750,12 +752,16 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
if (cpu->IdleThread)
|
||||
return NTLSTATUS_SUCCESS;
|
||||
|
||||
THREAD* idle = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||
THREAD* idle = (THREAD*)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||
if (!idle)
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
idle->Header.Destroy = (void *)0;
|
||||
idle->ThreadId = cpu->CpuIndex ? (0x80000000u | cpu->CpuIndex) : 0;
|
||||
idle->Header.Destroy = (void*)0;
|
||||
KSTATUS idStatus = KeAllocateThreadId(&idle->ThreadId);
|
||||
if (!KSUCCESS(idStatus)) {
|
||||
ObDereferenceObject(&idle->Header);
|
||||
return idStatus;
|
||||
}
|
||||
idle->State = ThreadRunning;
|
||||
idle->BaseSchedulingClass = KeSchedulingNormal;
|
||||
idle->BasePriority = PriorityLow;
|
||||
@@ -776,7 +782,7 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
idle->LastCpu = cpu->CpuIndex;
|
||||
idle->AffinityMask = (cpu->CpuIndex < 64) ? (1ULL << cpu->CpuIndex) : 0ULL;
|
||||
idle->Owner = gIdleProcess;
|
||||
idle->WaitObject = (OBJECT *)0;
|
||||
idle->WaitObject = (OBJECT*)0;
|
||||
idle->WaitStatus = NTLSTATUS_SUCCESS;
|
||||
idle->WaitListHead = (LIST_ENTRY*)0;
|
||||
idle->AlertableWait = 0;
|
||||
@@ -822,13 +828,13 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) {
|
||||
KeInitThreadFpuContext(idle);
|
||||
|
||||
// The hand-built CPU idle thread is not created through KeCreateThread(),
|
||||
// so register it manually with the idle process. This keeps PID 0 visible
|
||||
// as the real idle process while kernel worker threads live under PID 1.
|
||||
// so register it manually with the dedicated idle process while kernel worker
|
||||
// threads remain grouped under the system process.
|
||||
ObReferenceObject(&gIdleProcess->Header);
|
||||
uintptr_t idleFlags = KeAcquireSpinlock(&gIdleProcess->HandleLock);
|
||||
uintptr_t idleFlags = KeAcquireSpinlock(&gIdleProcess->ThreadLock);
|
||||
KeListInsertTailChecked(&gIdleProcess->ThreadList, &idle->ProcessLink);
|
||||
gIdleProcess->ThreadCount++;
|
||||
KeReleaseSpinlock(&gIdleProcess->HandleLock, idleFlags);
|
||||
KeReleaseSpinlock(&gIdleProcess->ThreadLock, idleFlags);
|
||||
|
||||
cpu->IdleThread = idle;
|
||||
cpu->CurrentThread = idle;
|
||||
@@ -1321,11 +1327,11 @@ static void KiTimeoutWorkRoutine(void* context) {
|
||||
|
||||
// Checks whether this CPU owns global scheduler tick duties.
|
||||
static int KiCpuOwnsGlobalSchedulerTick(const KCPU* cpu) {
|
||||
// LAPIC timer interrupts are per-CPU, but sleep deadlines, waitable timers,
|
||||
// Periodic timer interrupts are per-CPU, but sleep deadlines, waitable timers,
|
||||
// input repeat, and priority aging are global scheduler services. Keep the
|
||||
// global clock single-sourced on the BSP so enabling AP timers does not
|
||||
// global clock single-sourced on the boot processor so enabling AP timers does not
|
||||
// make those services run once per online CPU.
|
||||
return cpu && cpu->IsBsp;
|
||||
return cpu && cpu->IsBootProcessor;
|
||||
}
|
||||
|
||||
// Ages ready normal-class threads after enough global ticks have elapsed.
|
||||
@@ -1451,6 +1457,29 @@ void KeSchedulerTick(void) {
|
||||
KiRequestReschedule();
|
||||
}
|
||||
|
||||
// Converts one requested delay to scheduler ticks while reserving one phase guard tick.
|
||||
static uint64_t KiTimeoutTicksForMilliseconds(uint64_t milliseconds) {
|
||||
uint64_t ticks = milliseconds / SCHED_TICK_MS;
|
||||
if ((milliseconds % SCHED_TICK_MS) != 0)
|
||||
ticks++;
|
||||
|
||||
// The scheduler tick count identifies completed quanta, not the current
|
||||
// position inside one quantum. One additional tick guarantees that a
|
||||
// timeout armed immediately before an interrupt cannot expire early.
|
||||
if (ticks < UINT64_MAX)
|
||||
ticks++;
|
||||
return ticks ? ticks : 1;
|
||||
}
|
||||
|
||||
// Returns the saturated scheduler tick at which one finite timeout may expire.
|
||||
static uint64_t KiTimeoutWakeTickLocked(uint64_t milliseconds) {
|
||||
uint64_t ticks = KiTimeoutTicksForMilliseconds(milliseconds);
|
||||
uint64_t now = gSchedStats.Ticks;
|
||||
if (ticks == UINT64_MAX || ticks > UINT64_MAX - now)
|
||||
return UINT64_MAX;
|
||||
return now + ticks;
|
||||
}
|
||||
|
||||
// Arms a timeout for the current thread after a wait primitive has prepared it to block.
|
||||
KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus) {
|
||||
if (milliseconds == 0)
|
||||
@@ -1462,12 +1491,6 @@ KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus)
|
||||
if (!self || self->IsIdleThread)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t ticks = milliseconds / SCHED_TICK_MS;
|
||||
if ((milliseconds % SCHED_TICK_MS) != 0)
|
||||
ticks++;
|
||||
if (ticks == 0)
|
||||
ticks = 1;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSchedLock);
|
||||
if (self->State != ThreadWaiting ||
|
||||
self->RunningCpu != KeGetCurrentCpu()->CpuIndex ||
|
||||
@@ -1478,12 +1501,7 @@ KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint64_t now = gSchedStats.Ticks;
|
||||
uint64_t wakeTick = now + ticks;
|
||||
if (wakeTick < now)
|
||||
wakeTick = UINT64_MAX;
|
||||
|
||||
self->TimeoutTick = wakeTick;
|
||||
self->TimeoutTick = KiTimeoutWakeTickLocked(milliseconds);
|
||||
self->TimeoutStatus = timeoutStatus;
|
||||
self->TimeoutArmed = 1;
|
||||
KeListInsertTailChecked(&gTimeoutList, &self->TimeoutLink);
|
||||
@@ -1505,12 +1523,6 @@ __declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) {
|
||||
if (!self || self->IsIdleThread)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t ticks = milliseconds / SCHED_TICK_MS;
|
||||
if ((milliseconds % SCHED_TICK_MS) != 0)
|
||||
ticks++;
|
||||
if (ticks == 0)
|
||||
ticks = 1;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gSchedLock);
|
||||
|
||||
if (self->Queued || self->State != ThreadRunning ||
|
||||
@@ -1522,10 +1534,7 @@ __declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) {
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint64_t now = gSchedStats.Ticks;
|
||||
uint64_t wakeTick = now + ticks;
|
||||
if (wakeTick < now)
|
||||
wakeTick = UINT64_MAX;
|
||||
uint64_t wakeTick = KiTimeoutWakeTickLocked(milliseconds);
|
||||
|
||||
self->State = ThreadWaiting;
|
||||
self->WaitObject = (OBJECT*)0;
|
||||
|
||||
Reference in new issue
Block a user