first PID is 0, separate idle to system
This commit is contained in:
1 parent
0d7f71b693
commit
db175ab20a
7 files changed
+84
-25
No files matched your search
Binary file not shown.
@@ -14,7 +14,8 @@
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
static LIST_ENTRY gProcessList;
|
static LIST_ENTRY gProcessList;
|
||||||
static SPINLOCK gProcessListLock;
|
static SPINLOCK gProcessListLock;
|
||||||
static uint32_t gNextProcessId = 1;
|
static uint32_t gNextProcessId = 0;
|
||||||
|
static PROCESS* gSystemProcess = (PROCESS*)0;
|
||||||
|
|
||||||
static void KiProcessInit(void) {
|
static void KiProcessInit(void) {
|
||||||
static int inited = 0;
|
static int inited = 0;
|
||||||
@@ -38,6 +39,29 @@ PROCESS* KeGetCurrentProcess(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PROCESS* KeGetSystemProcess(void) {
|
||||||
|
return gSystemProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
KSTATUS KeCreateSystemProcess(PROCESS** out) {
|
||||||
|
if (!out) return STATUS_INVALID_PARAMETER;
|
||||||
|
if (gSystemProcess) {
|
||||||
|
*out = gSystemProcess;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS* proc = (PROCESS*)0;
|
||||||
|
KSTATUS s = KeCreateProcess("system", &proc);
|
||||||
|
if (!KSUCCESS(s)) {
|
||||||
|
*out = (PROCESS*)0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
gSystemProcess = proc;
|
||||||
|
*out = proc;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
||||||
KiProcessInit();
|
KiProcessInit();
|
||||||
|
|
||||||
@@ -59,6 +83,9 @@ size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
|||||||
static void KiProcessDestroy(OBJECT* obj) {
|
static void KiProcessDestroy(OBJECT* obj) {
|
||||||
PROCESS* proc = CONTAINING_RECORD(obj, PROCESS, Header);
|
PROCESS* proc = CONTAINING_RECORD(obj, PROCESS, Header);
|
||||||
|
|
||||||
|
if (proc == gSystemProcess)
|
||||||
|
gSystemProcess = (PROCESS*)0;
|
||||||
|
|
||||||
// Release all remaining handles.
|
// Release all remaining handles.
|
||||||
for (int i = 1; i < HANDLE_TABLE_SIZE; i++) {
|
for (int i = 1; i < HANDLE_TABLE_SIZE; i++) {
|
||||||
if (proc->Handles[i]) {
|
if (proc->Handles[i]) {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ typedef struct PROCESS {
|
|||||||
} PROCESS;
|
} PROCESS;
|
||||||
|
|
||||||
KSTATUS KeCreateProcess(const char* name, PROCESS **out);
|
KSTATUS KeCreateProcess(const char* name, PROCESS **out);
|
||||||
|
KSTATUS KeCreateSystemProcess(PROCESS** out);
|
||||||
KSTATUS KeSetupUserProcessEnvironment(PROCESS* process, const char* imagePath, const char* commandLine, const char* currentDirectory);
|
KSTATUS KeSetupUserProcessEnvironment(PROCESS* process, const char* imagePath, const char* commandLine, const char* currentDirectory);
|
||||||
void KeExitProcess(PROCESS* process, int exitCode);
|
void KeExitProcess(PROCESS* process, int exitCode);
|
||||||
KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut);
|
KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut);
|
||||||
@@ -81,6 +82,7 @@ OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle);
|
|||||||
/* Return the global process list head (kernel-internal). */
|
/* Return the global process list head (kernel-internal). */
|
||||||
LIST_ENTRY* KeGetProcessList(void);
|
LIST_ENTRY* KeGetProcessList(void);
|
||||||
PROCESS* KeGetCurrentProcess(void);
|
PROCESS* KeGetCurrentProcess(void);
|
||||||
|
PROCESS* KeGetSystemProcess(void);
|
||||||
/* Copy a snapshot of process IDs into caller-provided storage. */
|
/* Copy a snapshot of process IDs into caller-provided storage. */
|
||||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount);
|
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount);
|
||||||
/* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */
|
/* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */
|
||||||
|
|||||||
+24
-1
@@ -33,7 +33,13 @@ void KeInitializeScheduler(void) {
|
|||||||
gSchedLock = (SPINLOCK)SPINLOCK_INIT;
|
gSchedLock = (SPINLOCK)SPINLOCK_INIT;
|
||||||
|
|
||||||
PROCESS* idleProc;
|
PROCESS* idleProc;
|
||||||
KeCreateProcess("idle", &idleProc);
|
KSTATUS s = KeCreateProcess("idle", &idleProc);
|
||||||
|
if (!KSUCCESS(s)) return;
|
||||||
|
|
||||||
|
PROCESS* systemProc;
|
||||||
|
s = KeCreateSystemProcess(&systemProc);
|
||||||
|
if (!KSUCCESS(s)) return;
|
||||||
|
(void)systemProc;
|
||||||
|
|
||||||
THREAD* idle = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
THREAD* idle = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD));
|
||||||
idle->Header.Destroy = (void *)0;
|
idle->Header.Destroy = (void *)0;
|
||||||
@@ -44,9 +50,17 @@ void KeInitializeScheduler(void) {
|
|||||||
idle->Owner = idleProc;
|
idle->Owner = idleProc;
|
||||||
idle->WaitObject = (OBJECT *)0;
|
idle->WaitObject = (OBJECT *)0;
|
||||||
idle->WaitStatus = STATUS_SUCCESS;
|
idle->WaitStatus = STATUS_SUCCESS;
|
||||||
|
idle->WaitListHead = (LIST_ENTRY*)0;
|
||||||
|
idle->AlertableWait = 0;
|
||||||
idle->SchedLockFlags = 0x202ULL; // IF=1
|
idle->SchedLockFlags = 0x202ULL; // IF=1
|
||||||
|
idle->UserStackBase = (void*)0;
|
||||||
|
idle->Teb = (void*)0;
|
||||||
|
idle->TebSize = 0;
|
||||||
|
idle->ExitEvent = (EVENT*)0;
|
||||||
KiInitializeApcState(idle);
|
KiInitializeApcState(idle);
|
||||||
idle->TrapFrame = (KTRAP_FRAME*)0;
|
idle->TrapFrame = (KTRAP_FRAME*)0;
|
||||||
|
LIST_INIT(&idle->ProcessLink);
|
||||||
|
LIST_INIT(&idle->SchedulerLink);
|
||||||
|
|
||||||
void* kstack = MmAllocatePool(KSTACK_SIZE);
|
void* kstack = MmAllocatePool(KSTACK_SIZE);
|
||||||
idle->KernelStackBase = kstack;
|
idle->KernelStackBase = kstack;
|
||||||
@@ -61,6 +75,15 @@ void KeInitializeScheduler(void) {
|
|||||||
idle->SavedContext = ctx;
|
idle->SavedContext = ctx;
|
||||||
KeInitThreadFpuContext(idle);
|
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.
|
||||||
|
ObReferenceObject(&idleProc->Header);
|
||||||
|
uintptr_t idleFlags = KeAcquireSpinlock(&idleProc->HandleLock);
|
||||||
|
ListInsertTail(&idleProc->ThreadList, &idle->ProcessLink);
|
||||||
|
idleProc->ThreadCount++;
|
||||||
|
KeReleaseSpinlock(&idleProc->HandleLock, idleFlags);
|
||||||
|
|
||||||
gIdleThread = idle;
|
gIdleThread = idle;
|
||||||
gCurrentThread = idle;
|
gCurrentThread = idle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,10 +211,14 @@ extern void KeKernelThreadEntry(void);
|
|||||||
|
|
||||||
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||||
THREAD_PRIORITY priority, THREAD** out) {
|
THREAD_PRIORITY priority, THREAD** out) {
|
||||||
// Kernel threads are owned by the idle process. We need a PROCESS* for
|
// Kernel worker threads are owned by the system process. The scheduler's
|
||||||
// the owner field; grab it from the idle/init thread that already exists.
|
// hand-built CPU idle thread stays attached to PID 0 (idle), while driver,
|
||||||
THREAD* idleThread = KeGetCurrentThread(); // safe to call before scheduler starts
|
// async I/O, and init worker threads are grouped under PID 1 (system).
|
||||||
PROCESS* owner = idleThread ? idleThread->Owner : (PROCESS*)0;
|
PROCESS* owner = KeGetSystemProcess();
|
||||||
|
if (!owner) {
|
||||||
|
THREAD* currentThread = KeGetCurrentThread();
|
||||||
|
owner = currentThread ? currentThread->Owner : (PROCESS*)0;
|
||||||
|
}
|
||||||
if (!owner) return STATUS_INVALID_PARAMETER;
|
if (!owner) return STATUS_INVALID_PARAMETER;
|
||||||
if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER;
|
if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui
|
|||||||
|
|
||||||
// Create a kernel-mode-only thread. fn is called directly in ring 0 with
|
// Create a kernel-mode-only thread. fn is called directly in ring 0 with
|
||||||
// arg; when fn returns the thread exits automatically. No user stack or TEB
|
// arg; when fn returns the thread exits automatically. No user stack or TEB
|
||||||
// is allocated. The thread is owned by the idle process and runs at the
|
// is allocated. The thread is owned by the system process and runs at the
|
||||||
// given priority.
|
// given priority.
|
||||||
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg,
|
||||||
THREAD_PRIORITY priority, THREAD** out);
|
THREAD_PRIORITY priority, THREAD** out);
|
||||||
|
|||||||
+21
-18
@@ -370,24 +370,6 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
|||||||
// Caller owns the reference returned by KeCreateProcess.
|
// Caller owns the reference returned by KeCreateProcess.
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
static void KiPrintProcessList() {
|
|
||||||
LIST_ENTRY* listHead = KeGetProcessList();
|
|
||||||
LIST_ENTRY* current;
|
|
||||||
|
|
||||||
DbgPrint("\nPID | Name | Threads | ExitCode\n");
|
|
||||||
DbgPrint("---------------------------------------------\n");
|
|
||||||
|
|
||||||
for (current = listHead->Fwd; current != listHead; current = current->Fwd) {
|
|
||||||
// Translate the list entry back to the PROCESS structure
|
|
||||||
PROCESS* proc = CONTAINING_RECORD(current, PROCESS, GlobalLink);
|
|
||||||
|
|
||||||
DbgPrint("%-5u | %-16s | %-7u | %d\n",
|
|
||||||
proc->ProcessId,
|
|
||||||
proc->Name,
|
|
||||||
proc->ThreadCount,
|
|
||||||
proc->ExitCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemInitThread(void* arg) {
|
void SystemInitThread(void* arg) {
|
||||||
SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg;
|
SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg;
|
||||||
@@ -487,6 +469,27 @@ uint64_t KeCatchAllDebugBucket(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a0 == 2) {
|
||||||
|
LIST_ENTRY* listHead = KeGetProcessList();
|
||||||
|
LIST_ENTRY* current;
|
||||||
|
|
||||||
|
DbgPrint("\nPID | Name | Threads | ExitCode\n");
|
||||||
|
DbgPrint("---------------------------------------------\n");
|
||||||
|
|
||||||
|
for (current = listHead->Fwd; current != listHead; current = current->Fwd) {
|
||||||
|
// Translate the list entry back to the PROCESS structure
|
||||||
|
PROCESS* proc = CONTAINING_RECORD(current, PROCESS, GlobalLink);
|
||||||
|
|
||||||
|
DbgPrint("%-5u | %-16s | %-7u | %d\n",
|
||||||
|
proc->ProcessId,
|
||||||
|
proc->Name,
|
||||||
|
proc->ThreadCount,
|
||||||
|
proc->ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DbgPrint("DebugBucket: unknown command %llu\n", a0);
|
DbgPrint("DebugBucket: unknown command %llu\n", a0);
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user