- Simplify KiSelectReadyThread.
[reactos.git] / reactos / ntoskrnl / ke / thrdobj.c
index 33a9423..5033dc6 100644 (file)
-/*\r
- * PROJECT:         ReactOS Kernel\r
- * LICENSE:         GPL - See COPYING in the top level directory\r
- * FILE:            ntoskrnl/ke/thrdobj.c\r
- * PURPOSE:         Implements routines to manage the Kernel Thread Object\r
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];\r
-extern LIST_ENTRY PspReaperListHead;\r
-\r
-ULONG KiMask32Array[MAXIMUM_PRIORITY] =\r
-{\r
-    0x1,        0x2,       0x4,       0x8,       0x10,       0x20,\r
-    0x40,       0x80,      0x100,     0x200,     0x4000,     0x800,\r
-    0x1000,     0x2000,    0x4000,    0x8000,    0x10000,    0x20000,\r
-    0x40000,    0x80000,   0x100000,  0x200000,  0x400000,   0x800000,\r
-    0x1000000,  0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,\r
-    0x40000000, 0x80000000\r
-};\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-UCHAR\r
-NTAPI\r
-KeFindNextRightSetAffinity(IN UCHAR Number,\r
-                           IN ULONG Set)\r
-{\r
-    ULONG Bit, Result;\r
-    ASSERT(Set != 0);\r
-\r
-    /* Calculate the mask */\r
-    Bit = (AFFINITY_MASK(Number) - 1) & Set;\r
-\r
-    /* If it's 0, use the one we got */\r
-    if (!Bit) Bit = Set;\r
-\r
-    /* Now find the right set and return it */\r
-    BitScanReverse(&Result, Bit);\r
-    return (UCHAR)Result;\r
-}\r
-\r
-KPRIORITY\r
-NTAPI\r
-KeQueryBasePriorityThread(IN PKTHREAD Thread)\r
-{\r
-    LONG BaseIncrement;\r
-    KIRQL OldIrql;\r
-    PKPROCESS Process;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Raise IRQL to synch level */\r
-    OldIrql = KeRaiseIrqlToSynchLevel();\r
-\r
-    /* Lock the thread */\r
-    KiAcquireThreadLock(Thread);\r
-\r
-    /* Get the Process */\r
-    Process = Thread->ApcStatePointer[0]->Process;\r
-\r
-    /* Calculate the base increment */\r
-    BaseIncrement = Thread->BasePriority - Process->BasePriority;\r
-\r
-    /* If saturation occured, return the saturation increment instead */\r
-    if (Thread->Saturation) BaseIncrement = (HIGH_PRIORITY + 1) / 2 *\r
-                                            Thread->Saturation;\r
-\r
-    /* Release thread lock */\r
-    KiReleaseThreadLock(Thread);\r
-\r
-    /* Lower IRQl and return Increment */\r
-    KeLowerIrql(OldIrql);\r
-    return BaseIncrement;\r
-}\r
-\r
-ULONG\r
-NTAPI\r
-KeAlertResumeThread(IN PKTHREAD Thread)\r
-{\r
-    ULONG PreviousCount;\r
-    KLOCK_QUEUE_HANDLE ApcLock;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the Dispatcher Database and the APC Queue */\r
-    KiAcquireApcLock(Thread, &ApcLock);\r
-    KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-    /* Return if Thread is already alerted. */\r
-    if (!Thread->Alerted[KernelMode])\r
-    {\r
-        /* If it's Blocked, unblock if it we should */\r
-        if ((Thread->State == Waiting) && (Thread->Alertable))\r
-        {\r
-            /* Abort the wait */\r
-            KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);\r
-        }\r
-        else\r
-        {\r
-            /* If not, simply Alert it */\r
-            Thread->Alerted[KernelMode] = TRUE;\r
-        }\r
-    }\r
-\r
-    /* Save the old Suspend Count */\r
-    PreviousCount = Thread->SuspendCount;\r
-\r
-    /* If the thread is suspended, decrease one of the suspend counts */\r
-    if (PreviousCount)\r
-    {\r
-        /* Decrease count. If we are now zero, unwait it completely */\r
-        if (--Thread->SuspendCount)\r
-        {\r
-            /* Signal and satisfy */\r
-            Thread->SuspendSemaphore.Header.SignalState++;\r
-            KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
-        }\r
-    }\r
-\r
-    /* Release Locks and return the Old State */\r
-    KiReleaseDispatcherLockFromDpcLevel();\r
-    KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    KiExitDispatcher(ApcLock.OldIrql);\r
-    return PreviousCount;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KeAlertThread(IN PKTHREAD Thread,\r
-              IN KPROCESSOR_MODE AlertMode)\r
-{\r
-    BOOLEAN PreviousState;\r
-    KLOCK_QUEUE_HANDLE ApcLock;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the Dispatcher Database and the APC Queue */\r
-    KiAcquireApcLock(Thread, &ApcLock);\r
-    KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-    /* Save the Previous State */\r
-    PreviousState = Thread->Alerted[AlertMode];\r
-\r
-    /* Check if it's already alerted */\r
-    if (!PreviousState)\r
-    {\r
-        /* Check if the thread is alertable, and blocked in the given mode */\r
-        if ((Thread->State == Waiting) &&\r
-            ((AlertMode == KernelMode) || (Thread->WaitMode == AlertMode)) &&\r
-            (Thread->Alertable))\r
-        {\r
-            /* Abort the wait to alert the thread */\r
-            KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);\r
-        }\r
-        else\r
-        {\r
-            /* Otherwise, merely set the alerted state */\r
-            Thread->Alerted[AlertMode] = TRUE;\r
-        }\r
-    }\r
-\r
-    /* Release the Dispatcher Lock */\r
-    KiReleaseDispatcherLockFromDpcLevel();\r
-    KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    KiExitDispatcher(ApcLock.OldIrql);\r
-\r
-    /* Return the old state */\r
-    return PreviousState;\r
-}\r
-\r
-ULONG\r
-NTAPI\r
-KeForceResumeThread(IN PKTHREAD Thread)\r
-{\r
-    KLOCK_QUEUE_HANDLE ApcLock;\r
-    ULONG PreviousCount;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the APC Queue */\r
-    KiAcquireApcLock(Thread, &ApcLock);\r
-\r
-    /* Save the old Suspend Count */\r
-    PreviousCount = Thread->SuspendCount + Thread->FreezeCount;\r
-\r
-    /* If the thread is suspended, wake it up!!! */\r
-    if (PreviousCount)\r
-    {\r
-        /* Unwait it completely */\r
-        Thread->SuspendCount = 0;\r
-        Thread->FreezeCount = 0;\r
-\r
-        /* Lock the dispatcher */\r
-        KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-        /* Signal and satisfy */\r
-        Thread->SuspendSemaphore.Header.SignalState++;\r
-        KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
-\r
-        /* Release the dispatcher */\r
-        KiReleaseDispatcherLockFromDpcLevel();\r
-    }\r
-\r
-    /* Release Lock and return the Old State */\r
-    KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    KiExitDispatcher(ApcLock.OldIrql);\r
-    return PreviousCount;\r
-}\r
-\r
-/*\r
- * Used by the debugging code to freeze all the process's threads\r
- * while the debugger is examining their state.\r
- */\r
-VOID\r
-NTAPI\r
-KeFreezeAllThreads(IN PKPROCESS Process)\r
-{\r
-    KLOCK_QUEUE_HANDLE LockHandle, ApcLock;\r
-    PKTHREAD Current, CurrentThread = KeGetCurrentThread();\r
-    PLIST_ENTRY ListHead, NextEntry;\r
-    LONG OldCount;\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the process */\r
-    KiAcquireProcessLock(Process, &LockHandle);\r
-\r
-    /* If someone is already trying to free us, try again */\r
-    while (CurrentThread->FreezeCount)\r
-    {\r
-        /* Release and re-acquire the process lock so the APC will go through */\r
-        KiReleaseProcessLock(&LockHandle);\r
-        KiAcquireProcessLock(Process, &LockHandle);\r
-    }\r
-\r
-    /* Enter a critical region */\r
-    KeEnterCriticalRegion();\r
-\r
-    /* Loop the Process's Threads */\r
-    ListHead = &Process->ThreadListHead;\r
-    NextEntry = ListHead->Flink;\r
-    while (NextEntry != ListHead)\r
-    {\r
-        /* Get the current thread */\r
-        Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);\r
-\r
-        /* Lock it */\r
-        KiAcquireApcLockAtDpcLevel(Current, &ApcLock);\r
-\r
-        /* Make sure it's not ours, and check if APCs are enabled */\r
-        if ((Current != CurrentThread) && (Current->ApcQueueable))\r
-        {\r
-            /* Sanity check */\r
-            OldCount = Current->SuspendCount;\r
-            ASSERT(OldCount != MAXIMUM_SUSPEND_COUNT);\r
-\r
-            /* Increase the freeze count */\r
-            Current->FreezeCount++;\r
-\r
-            /* Make sure it wasn't already suspended */\r
-            if (!(OldCount) && !(Current->SuspendCount))\r
-            {\r
-                /* Did we already insert it? */\r
-                if (!Current->SuspendApc.Inserted)\r
-                {\r
-                    /* Insert the APC */\r
-                    Current->SuspendApc.Inserted = TRUE;\r
-                    KiInsertQueueApc(&Current->SuspendApc, IO_NO_INCREMENT);\r
-                }\r
-                else\r
-                {\r
-                    /* Lock the dispatcher */\r
-                    KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-                    /* Unsignal the semaphore, the APC was already inserted */\r
-                    Current->SuspendSemaphore.Header.SignalState--;\r
-\r
-                    /* Release the dispatcher */\r
-                    KiReleaseDispatcherLockFromDpcLevel();\r
-                }\r
-            }\r
-        }\r
-\r
-        /* Release the APC lock */\r
-        KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    }\r
-\r
-    /* Release the process lock and exit the dispatcher */\r
-    KiReleaseProcessLock(&LockHandle);\r
-    KiExitDispatcher(LockHandle.OldIrql);\r
-}\r
-\r
-ULONG\r
-NTAPI\r
-KeResumeThread(IN PKTHREAD Thread)\r
-{\r
-    KLOCK_QUEUE_HANDLE ApcLock;\r
-    ULONG PreviousCount;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the APC Queue */\r
-    KiAcquireApcLock(Thread, &ApcLock);\r
-\r
-    /* Save the Old Count */\r
-    PreviousCount = Thread->SuspendCount;\r
-\r
-    /* Check if it existed */\r
-    if (PreviousCount)\r
-    {\r
-        /* Decrease the suspend count */\r
-        Thread->SuspendCount--;\r
-\r
-        /* Check if the thrad is still suspended or not */\r
-        if ((!Thread->SuspendCount) && (!Thread->FreezeCount))\r
-        {\r
-            /* Acquire the dispatcher lock */\r
-            KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-            /* Signal the Suspend Semaphore */\r
-            Thread->SuspendSemaphore.Header.SignalState++;\r
-            KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
-\r
-            /* Release the dispatcher lock */\r
-            KiReleaseDispatcherLockFromDpcLevel();\r
-        }\r
-    }\r
-\r
-    /* Release APC Queue lock and return the Old State */\r
-    KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    KiExitDispatcher(ApcLock.OldIrql);\r
-    return PreviousCount;\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KeRundownThread(VOID)\r
-{\r
-    KIRQL OldIrql;\r
-    PKTHREAD Thread = KeGetCurrentThread();\r
-    PLIST_ENTRY NextEntry, ListHead;\r
-    PKMUTANT Mutant;\r
-\r
-    /* Optimized path if nothing is on the list at the moment */\r
-    if (IsListEmpty(&Thread->MutantListHead)) return;\r
-\r
-    /* Lock the Dispatcher Database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Get the List Pointers */\r
-    ListHead = &Thread->MutantListHead;\r
-    NextEntry = ListHead->Flink;\r
-    while (NextEntry != ListHead)\r
-    {\r
-        /* Get the Mutant */\r
-        Mutant = CONTAINING_RECORD(NextEntry, KMUTANT, MutantListEntry);\r
-\r
-        /* Make sure it's not terminating with APCs off */\r
-        if (Mutant->ApcDisable)\r
-        {\r
-            /* Bugcheck the system */\r
-            KEBUGCHECKEX(0, //THREAD_TERMINATE_HELD_MUTEX,\r
-                         (ULONG_PTR)Thread,\r
-                         (ULONG_PTR)Mutant,\r
-                         0,\r
-                         0);\r
-        }\r
-\r
-        /* Now we can remove it */\r
-        RemoveEntryList(&Mutant->MutantListEntry);\r
-\r
-        /* Unconditionally abandon it */\r
-        Mutant->Header.SignalState = 1;\r
-        Mutant->Abandoned = TRUE;\r
-        Mutant->OwnerThread = NULL;\r
-\r
-        /* Check if the Wait List isn't empty */\r
-        if (!IsListEmpty(&Mutant->Header.WaitListHead))\r
-        {\r
-            /* Wake the Mutant */\r
-            KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);\r
-        }\r
-\r
-        /* Move on */\r
-        NextEntry = NextEntry->Flink;\r
-    }\r
-\r
-    /* Release the Lock */\r
-    KiReleaseDispatcherLock(OldIrql);\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KeStartThread(IN OUT PKTHREAD Thread)\r
-{\r
-    KLOCK_QUEUE_HANDLE LockHandle;\r
-#ifdef CONFIG_SMP\r
-    PKNODE Node;\r
-    PKPRCB NodePrcb;\r
-    ULONG Set, Mask;\r
-#endif\r
-    UCHAR IdealProcessor = 0;\r
-    PKPROCESS Process = Thread->ApcState.Process;\r
-\r
-    /* Setup static fields from parent */\r
-    Thread->Iopl = Process->Iopl;\r
-    Thread->Quantum = Process->QuantumReset;\r
-    Thread->QuantumReset = Process->QuantumReset;\r
-    Thread->SystemAffinityActive = FALSE;\r
-\r
-    /* Lock the process */\r
-    KiAcquireProcessLock(Process, &LockHandle);\r
-\r
-    /* Setup volatile data */\r
-    Thread->Priority = Process->BasePriority;\r
-    Thread->BasePriority = Process->BasePriority;\r
-    Thread->Affinity = Process->Affinity;\r
-    Thread->UserAffinity = Process->Affinity;\r
-\r
-#ifdef CONFIG_SMP\r
-    /* Get the KNODE and its PRCB */\r
-    Node = KeNodeBlock[Process->IdealNode];\r
-    NodePrcb = (PKPRCB)(KPCR_BASE + (Process->ThreadSeed * PAGE_SIZE));\r
-\r
-    /* Calculate affinity mask */\r
-    Set = ~NodePrcb->MultiThreadProcessorSet;\r
-    Mask = (ULONG)(Node->ProcessorMask & Process->Affinity);\r
-    Set &= Mask;\r
-    if (Set) Mask = Set;\r
-\r
-    /* Get the new thread seed */\r
-    IdealProcessor = KeFindNextRightSetAffinity(Process->ThreadSeed, Mask);\r
-    Process->ThreadSeed = IdealProcessor;\r
-\r
-    /* Sanity check */\r
-    ASSERT((Thread->UserAffinity & AFFINITY_MASK(IdealProcessor)));\r
-#endif\r
-\r
-    /* Set the Ideal Processor */\r
-    Thread->IdealProcessor = IdealProcessor;\r
-    Thread->UserIdealProcessor = IdealProcessor;\r
-\r
-    /* Lock the Dispatcher Database */\r
-    KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-    /* Insert the thread into the process list */\r
-    InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);\r
-\r
-    /* Increase the stack count */\r
-    ASSERT(Process->StackCount != MAXULONG_PTR);\r
-    Process->StackCount++;\r
-\r
-    /* Release locks and return */\r
-    KiReleaseDispatcherLockFromDpcLevel();\r
-    KiReleaseProcessLock(&LockHandle);\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KiSuspendRundown(IN PKAPC Apc)\r
-{\r
-    /* Does nothing */\r
-    UNREFERENCED_PARAMETER(Apc);\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KiSuspendNop(IN PKAPC Apc,\r
-             IN PKNORMAL_ROUTINE *NormalRoutine,\r
-             IN PVOID *NormalContext,\r
-             IN PVOID *SystemArgument1,\r
-             IN PVOID *SystemArgument2)\r
-{\r
-    /* Does nothing */\r
-    UNREFERENCED_PARAMETER(Apc);\r
-    UNREFERENCED_PARAMETER(NormalRoutine);\r
-    UNREFERENCED_PARAMETER(NormalContext);\r
-    UNREFERENCED_PARAMETER(SystemArgument1);\r
-    UNREFERENCED_PARAMETER(SystemArgument2);\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KiSuspendThread(IN PVOID NormalContext,\r
-                IN PVOID SystemArgument1,\r
-                IN PVOID SystemArgument2)\r
-{\r
-    /* Non-alertable kernel-mode suspended wait */\r
-    KeWaitForSingleObject(&KeGetCurrentThread()->SuspendSemaphore,\r
-                          Suspended,\r
-                          KernelMode,\r
-                          FALSE,\r
-                          NULL);\r
-}\r
-\r
-NTSTATUS\r
-NTAPI\r
-KeSuspendThread(PKTHREAD Thread)\r
-{\r
-    KLOCK_QUEUE_HANDLE ApcLock;\r
-    ULONG PreviousCount;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the APC Queue */\r
-    KiAcquireApcLock(Thread, &ApcLock);\r
-\r
-    /* Save the Old Count */\r
-    PreviousCount = Thread->SuspendCount;\r
-\r
-    /* Handle the maximum */\r
-    if (PreviousCount == MAXIMUM_SUSPEND_COUNT)\r
-    {\r
-        /* Raise an exception */\r
-        KiReleaseApcLock(&ApcLock);\r
-        RtlRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);\r
-    }\r
-\r
-    /* Should we bother to queue at all? */\r
-    if (Thread->ApcQueueable)\r
-    {\r
-        /* Increment the suspend count */\r
-        Thread->SuspendCount++;\r
-\r
-        /* Check if we should suspend it */\r
-        if (!(PreviousCount) && !(Thread->FreezeCount))\r
-        {\r
-            /* Is the APC already inserted? */\r
-            if (!Thread->SuspendApc.Inserted)\r
-            {\r
-                /* Not inserted, insert it */\r
-                Thread->SuspendApc.Inserted = TRUE;\r
-                KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT);\r
-            }\r
-            else\r
-            {\r
-                /* Lock the dispatcher */\r
-                KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-                /* Unsignal the semaphore, the APC was already inserted */\r
-                Thread->SuspendSemaphore.Header.SignalState--;\r
-\r
-                /* Release the dispatcher */\r
-                KiReleaseDispatcherLockFromDpcLevel();\r
-            }\r
-        }\r
-    }\r
-\r
-    /* Release Lock and return the Old State */\r
-    KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    KiExitDispatcher(ApcLock.OldIrql);\r
-    return PreviousCount;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)\r
-{\r
-    PKTHREAD Thread = KeGetCurrentThread();\r
-    BOOLEAN OldState;\r
-    KLOCK_QUEUE_HANDLE ApcLock;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the Dispatcher Database and the APC Queue */\r
-    KiAcquireApcLock(Thread, &ApcLock);\r
-    KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-    /* Save the old State */\r
-    OldState = Thread->Alerted[AlertMode];\r
-\r
-    /* Check the Thread is alerted */\r
-    if (OldState)\r
-    {\r
-        /* Disable alert for this mode */\r
-        Thread->Alerted[AlertMode] = FALSE;\r
-    }\r
-    else if ((AlertMode != KernelMode) &&\r
-             (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))\r
-    {\r
-        /* If the mode is User and the Queue isn't empty, set Pending */\r
-        Thread->ApcState.UserApcPending = TRUE;\r
-    }\r
-\r
-    /* Release Locks and return the Old State */\r
-    KiReleaseDispatcherLockFromDpcLevel();\r
-    KiReleaseApcLockFromDpcLevel(&ApcLock);\r
-    KiExitDispatcher(ApcLock.OldIrql);\r
-    return OldState;\r
-}\r
-\r
-NTSTATUS\r
-NTAPI\r
-KeInitThread(IN OUT PKTHREAD Thread,\r
-             IN PVOID KernelStack,\r
-             IN PKSYSTEM_ROUTINE SystemRoutine,\r
-             IN PKSTART_ROUTINE StartRoutine,\r
-             IN PVOID StartContext,\r
-             IN PCONTEXT Context,\r
-             IN PVOID Teb,\r
-             IN PKPROCESS Process)\r
-{\r
-    BOOLEAN AllocatedStack = FALSE;\r
-    ULONG i;\r
-    PKWAIT_BLOCK TimerWaitBlock;\r
-    PKTIMER Timer;\r
-    NTSTATUS Status;\r
-\r
-    /* Initalize the Dispatcher Header */\r
-    KeInitializeDispatcherHeader(&Thread->DispatcherHeader,\r
-                                 ThreadObject,\r
-                                 sizeof(KTHREAD) / sizeof(LONG),\r
-                                 FALSE);\r
-\r
-    /* Initialize the Mutant List */\r
-    InitializeListHead(&Thread->MutantListHead);\r
-\r
-    /* Initialize the wait blocks */\r
-    for (i = 0; i< (THREAD_WAIT_OBJECTS + 1); i++)\r
-    {\r
-        /* Put our pointer */\r
-        Thread->WaitBlock[i].Thread = Thread;\r
-    }\r
-\r
-    /* Set swap settings */\r
-    Thread->EnableStackSwap = FALSE;//TRUE;\r
-    Thread->IdealProcessor = 1;\r
-    Thread->SwapBusy = FALSE;\r
-    Thread->AdjustReason = 0;\r
-\r
-    /* Initialize the lock */\r
-    KeInitializeSpinLock(&Thread->ThreadLock);\r
-\r
-    /* Setup the Service Descriptor Table for Native Calls */\r
-    Thread->ServiceTable = KeServiceDescriptorTable;\r
-\r
-    /* Setup APC Fields */\r
-    InitializeListHead(&Thread->ApcState.ApcListHead[0]);\r
-    InitializeListHead(&Thread->ApcState.ApcListHead[1]);\r
-    Thread->ApcState.Process = Process;\r
-    Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;\r
-    Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;\r
-    Thread->ApcStateIndex = OriginalApcEnvironment;\r
-    Thread->ApcQueueable = TRUE;\r
-    KeInitializeSpinLock(&Thread->ApcQueueLock);\r
-\r
-    /* Initialize the Suspend APC */\r
-    KeInitializeApc(&Thread->SuspendApc,\r
-                    Thread,\r
-                    OriginalApcEnvironment,\r
-                    KiSuspendNop,\r
-                    KiSuspendRundown,\r
-                    KiSuspendThread,\r
-                    KernelMode,\r
-                    NULL);\r
-\r
-    /* Initialize the Suspend Semaphore */\r
-    KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 2);\r
-\r
-    /* Setup the timer */\r
-    Timer = &Thread->Timer;\r
-    KeInitializeTimer(Timer);\r
-    TimerWaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
-    TimerWaitBlock->Object = Timer;\r
-    TimerWaitBlock->WaitKey = STATUS_TIMEOUT;\r
-    TimerWaitBlock->WaitType = WaitAny;\r
-    TimerWaitBlock->NextWaitBlock = NULL;\r
-\r
-    /* Link the two wait lists together */\r
-    TimerWaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead;\r
-    TimerWaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead;\r
-\r
-    /* Set the TEB */\r
-    Thread->Teb = Teb;\r
-\r
-    /* Check if we have a kernel stack */\r
-    if (!KernelStack)\r
-    {\r
-        /* We don't, allocate one */\r
-        KernelStack = (PVOID)((ULONG_PTR)MmCreateKernelStack(FALSE) +\r
-                              KERNEL_STACK_SIZE);\r
-        if (!KernelStack) return STATUS_INSUFFICIENT_RESOURCES;\r
-\r
-        /* Remember for later */\r
-        AllocatedStack = TRUE;\r
-    }\r
-\r
-    /* Set the Thread Stacks */\r
-    Thread->InitialStack = (PCHAR)KernelStack;\r
-    Thread->StackBase = (PCHAR)KernelStack;\r
-    Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;\r
-    Thread->KernelStackResident = TRUE;\r
-\r
-    /* ROS Mm HACK */\r
-    MmUpdatePageDir((PEPROCESS)Process,\r
-                    (PVOID)Thread->StackLimit,\r
-                    KERNEL_STACK_SIZE);\r
-    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));\r
-\r
-    /* Enter SEH to avoid crashes due to user mode */\r
-    Status = STATUS_SUCCESS;\r
-    _SEH_TRY\r
-    {\r
-        /* Initalize the Thread Context */\r
-        Ke386InitThreadWithContext(Thread,\r
-                                   SystemRoutine,\r
-                                   StartRoutine,\r
-                                   StartContext,\r
-                                   Context);\r
-    }\r
-    _SEH_HANDLE\r
-    {\r
-        /* Set failure status */\r
-        Status = STATUS_UNSUCCESSFUL;\r
-\r
-        /* Check if a stack was allocated */\r
-        if (AllocatedStack)\r
-        {\r
-            /* Delete the stack */\r
-            MmDeleteKernelStack(Thread->StackBase, FALSE);\r
-            Thread->InitialStack = NULL;\r
-        }\r
-    }\r
-    _SEH_END;\r
-\r
-    /* Set the Thread to initalized */\r
-    Thread->State = Initialized;\r
-    return Status;\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KeInitializeThread(IN PKPROCESS Process,\r
-                   IN OUT PKTHREAD Thread,\r
-                   IN PKSYSTEM_ROUTINE SystemRoutine,\r
-                   IN PKSTART_ROUTINE StartRoutine,\r
-                   IN PVOID StartContext,\r
-                   IN PCONTEXT Context,\r
-                   IN PVOID Teb,\r
-                   IN PVOID KernelStack)\r
-{\r
-    /* Initailize and start the thread on success */\r
-    if (NT_SUCCESS(KeInitThread(Thread,\r
-                                KernelStack,\r
-                                SystemRoutine,\r
-                                StartRoutine,\r
-                                StartContext,\r
-                                Context,\r
-                                Teb,\r
-                                Process)))\r
-    {\r
-        /* Start it */\r
-        KeStartThread(Thread);\r
-    }\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KeUninitThread(IN PKTHREAD Thread)\r
-{\r
-    /* Delete the stack */\r
-    MmDeleteKernelStack(Thread->StackBase, FALSE);\r
-    Thread->InitialStack = NULL;\r
-}\r
-\r
-/* PUBLIC FUNCTIONS **********************************************************/\r
-\r
-/*\r
- * @unimplemented\r
- */\r
-VOID\r
-NTAPI\r
-KeCapturePersistentThreadState(IN PVOID CurrentThread,\r
-                               IN ULONG Setting1,\r
-                               IN ULONG Setting2,\r
-                               IN ULONG Setting3,\r
-                               IN ULONG Setting4,\r
-                               IN ULONG Setting5,\r
-                               IN PVOID ThreadState)\r
-{\r
-    UNIMPLEMENTED;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-#undef KeGetCurrentThread\r
-PKTHREAD\r
-NTAPI\r
-KeGetCurrentThread(VOID)\r
-{\r
-    /* Return the current thread on this PCR */\r
-    return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-KPROCESSOR_MODE\r
-NTAPI\r
-KeGetPreviousMode(VOID)\r
-{\r
-    /* Return the previous mode of this thread */\r
-    return KeGetCurrentThread()->PreviousMode;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-ULONG\r
-NTAPI\r
-KeQueryRuntimeThread(IN PKTHREAD Thread,\r
-                     OUT PULONG UserTime)\r
-{\r
-    ASSERT_THREAD(Thread);\r
-\r
-    /* Return the User Time */\r
-    *UserTime = Thread->UserTime;\r
-\r
-    /* Return the Kernel Time */\r
-    return Thread->KernelTime;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOLEAN\r
-NTAPI\r
-KeSetKernelStackSwapEnable(IN BOOLEAN Enable)\r
-{\r
-    BOOLEAN PreviousState;\r
-    PKTHREAD Thread = KeGetCurrentThread();\r
-\r
-    /* Save Old State */\r
-    PreviousState = Thread->EnableStackSwap;\r
-\r
-    /* Set New State */\r
-    Thread->EnableStackSwap = Enable;\r
-\r
-    /* Return Old State */\r
-    return PreviousState;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-KPRIORITY\r
-NTAPI\r
-KeQueryPriorityThread(IN PKTHREAD Thread)\r
-{\r
-    ASSERT_THREAD(Thread);\r
-\r
-    /* Return the current priority */\r
-    return Thread->Priority;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-VOID\r
-NTAPI\r
-KeRevertToUserAffinityThread(VOID)\r
-{\r
-    KIRQL OldIrql;\r
-    PKPRCB Prcb;\r
-    PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-    ASSERT(CurrentThread->SystemAffinityActive != FALSE);\r
-\r
-    /* Lock the Dispatcher Database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Set the user affinity and processor and disable system affinity */\r
-    CurrentThread->Affinity = CurrentThread->UserAffinity;\r
-    CurrentThread->IdealProcessor = CurrentThread->UserIdealProcessor;\r
-    CurrentThread->SystemAffinityActive = FALSE;\r
-\r
-    /* Get the current PRCB and check if it doesn't match this affinity */\r
-    Prcb = KeGetCurrentPrcb();\r
-    if (!(Prcb->SetMember & CurrentThread->Affinity))\r
-    {\r
-        /* Lock the PRCB */\r
-        KiAcquirePrcbLock(Prcb);\r
-\r
-#ifdef NEW_SCHEDULER\r
-        /* Check if there's no next thread scheduled */\r
-        if (!Prcb->NextThread)\r
-        {\r
-            /* Select a new thread and set it on standby */\r
-            NextThread = KiSelectNextThread(Prcb);\r
-            NextThread->State = Standby;\r
-            Prcb->NextThread = NextThread;\r
-        }\r
-#else\r
-        /* We need to dispatch a new thread */\r
-        NextThread = NULL;\r
-        CurrentThread->WaitIrql = OldIrql;\r
-        KiDispatchThreadNoLock(Ready);\r
-        KeLowerIrql(OldIrql);\r
-        return;\r
-#endif\r
-\r
-        /* Release the PRCB lock */\r
-        KiReleasePrcbLock(Prcb);\r
-    }\r
-\r
-    /* Unlock dispatcher database */\r
-    KiReleaseDispatcherLock(OldIrql);\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-UCHAR\r
-NTAPI\r
-KeSetIdealProcessorThread(IN PKTHREAD Thread,\r
-                          IN UCHAR Processor)\r
-{\r
-    CCHAR OldIdealProcessor;\r
-    KIRQL OldIrql;\r
-    ASSERT(Processor <= MAXIMUM_PROCESSORS);\r
-\r
-    /* Lock the Dispatcher Database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Save Old Ideal Processor */\r
-    OldIdealProcessor = Thread->UserIdealProcessor;\r
-\r
-    /* Make sure a valid CPU was given */\r
-    if (Processor < MAXIMUM_PROCESSORS)\r
-    {\r
-        /* Check if the user ideal CPU is in the affinity */\r
-        if (Thread->UserIdealProcessor & AFFINITY_MASK(Processor))\r
-        {\r
-            /* Set the ideal processor */\r
-            Thread->IdealProcessor = Processor;\r
-\r
-            /* Check if system affinity is used */\r
-            if (!Thread->SystemAffinityActive)\r
-            {\r
-                /* It's not, so update the user CPU too */\r
-                Thread->UserIdealProcessor = Processor;\r
-            }\r
-        }\r
-    }\r
-\r
-    /* Release dispatcher lock and return the old ideal CPU */\r
-    KiReleaseDispatcherLock(OldIrql);\r
-    return OldIdealProcessor;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-VOID\r
-NTAPI\r
-KeSetSystemAffinityThread(IN KAFFINITY Affinity)\r
-{\r
-    KIRQL OldIrql;\r
-    PKPRCB Prcb;\r
-    PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-    ASSERT((Affinity & KeActiveProcessors) != 0);\r
-\r
-    /* Lock the Dispatcher Database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Restore the affinity and enable system affinity */\r
-    CurrentThread->Affinity = Affinity;\r
-    CurrentThread->SystemAffinityActive = TRUE;\r
-\r
-    /* Check if the ideal processor is part of the affinity */\r
-#ifdef CONFIG_SMP\r
-    if (!(Affinity & AFFINITY_MASK(CurrentThread->IdealProcessor)))\r
-    {\r
-        ULONG AffinitySet, NodeMask;\r
-\r
-        /* It's not! Get the PRCB */\r
-        Prcb = KiProcessorBlock[CurrentThread->IdealProcessor];\r
-\r
-        /* Calculate the affinity set */\r
-        AffinitySet = KeActiveProcessors & Affinity;\r
-        NodeMask = Prcb->ParentNode->ProcessorMask & AffinitySet;\r
-        if (NodeMask)\r
-        {\r
-            /* Use the Node set instead */\r
-            AffinitySet = NodeMask;\r
-        }\r
-\r
-        /* Calculate the ideal CPU from the affinity set */\r
-        BitScanReverse(&NodeMask, AffinitySet);\r
-        CurrentThread->IdealProcessor = (UCHAR)NodeMask;\r
-    }\r
-#endif\r
-\r
-    /* Get the current PRCB and check if it doesn't match this affinity */\r
-    Prcb = KeGetCurrentPrcb();\r
-    if (!(Prcb->SetMember & CurrentThread->Affinity))\r
-    {\r
-        /* Lock the PRCB */\r
-        KiAcquirePrcbLock(Prcb);\r
-\r
-#ifdef NEW_SCHEDULER\r
-        /* Check if there's no next thread scheduled */\r
-        if (!Prcb->NextThread)\r
-        {\r
-            /* Select a new thread and set it on standby */\r
-            NextThread = KiSelectNextThread(Prcb);\r
-            NextThread->State = Standby;\r
-            Prcb->NextThread = NextThread;\r
-        }\r
-#else\r
-        /* We need to dispatch a new thread */\r
-        NextThread = NULL;\r
-        CurrentThread->WaitIrql = OldIrql;\r
-        KiDispatchThreadNoLock(Ready);\r
-        KeLowerIrql(OldIrql);\r
-        return;\r
-#endif\r
-\r
-        /* Release the PRCB lock */\r
-        KiReleasePrcbLock(Prcb);\r
-    }\r
-\r
-    /* Unlock dispatcher database */\r
-    KiReleaseDispatcherLock(OldIrql);\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-LONG\r
-NTAPI\r
-KeSetBasePriorityThread(IN PKTHREAD Thread,\r
-                        IN LONG Increment)\r
-{\r
-    KIRQL OldIrql;\r
-    KPRIORITY OldBasePriority, Priority, BasePriority;\r
-    LONG OldIncrement;\r
-    PKPROCESS Process;\r
-    BOOLEAN Released;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Get the process */\r
-    Process = Thread->ApcState.Process;\r
-\r
-    /* Lock the Dispatcher Database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Lock the thread */\r
-    KiAcquireThreadLock(Thread);\r
-\r
-    /* Save the old base priority and increment */\r
-    OldBasePriority = Thread->BasePriority;\r
-    OldIncrement = OldBasePriority - Process->BasePriority;\r
-\r
-    /* If priority saturation happened, use the saturated increment */\r
-    if (Thread->Saturation) OldIncrement = (HIGH_PRIORITY + 1) / 2 *\r
-                                            Thread->Saturation;\r
-\r
-    /* Now check if saturation is being used for the new value */\r
-    if (abs(Increment) >= ((HIGH_PRIORITY + 1) / 2))\r
-    {\r
-        /* Check if we need positive or negative saturation */\r
-        Thread->Saturation = (Increment > 0) ? 1 : -1;\r
-    }\r
-\r
-    /* Normalize the Base Priority */\r
-    BasePriority = Process->BasePriority + Increment;\r
-    if (Process->BasePriority >= LOW_REALTIME_PRIORITY)\r
-    {\r
-        /* Check if it's too low */\r
-        if (BasePriority < LOW_REALTIME_PRIORITY)\r
-        {\r
-            /* Set it to the lowest real time level */\r
-            BasePriority = LOW_REALTIME_PRIORITY;\r
-        }\r
-\r
-        /* Check if it's too high */\r
-        if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;\r
-\r
-        /* We are at real time, so use the raw base priority */\r
-        Priority = BasePriority;\r
-    }\r
-    else\r
-    {\r
-        /* Check if it's entering the real time range */\r
-        if (BasePriority >= LOW_REALTIME_PRIORITY)\r
-        {\r
-            /* Set it to the highest dynamic level */\r
-            BasePriority = LOW_REALTIME_PRIORITY - 1;\r
-        }\r
-\r
-        /* Check if it's too low and normalize it */\r
-        if (BasePriority <= LOW_PRIORITY) BasePriority = 1;\r
-\r
-        /* Check if Saturation is used */\r
-        if (Thread->Saturation)\r
-        {\r
-            /* Use the raw base priority */\r
-            Priority = BasePriority;\r
-        }\r
-        else\r
-        {\r
-            /* Otherwise, calculate the new priority */\r
-            Priority = KiComputeNewPriority(Thread);\r
-\r
-            /* Check if it entered the real-time range */\r
-            if (Priority >= LOW_REALTIME_PRIORITY)\r
-            {\r
-                /* Normalize it down to the highest dynamic priority */\r
-                Priority = LOW_REALTIME_PRIORITY - 1;\r
-            }\r
-        }\r
-    }\r
-\r
-    /* Finally set the new base priority */\r
-    Thread->BasePriority = (SCHAR)BasePriority;\r
-\r
-    /* Reset the decrements */\r
-    Thread->PriorityDecrement = 0;\r
-\r
-    /* Check if we're changing priority after all */\r
-    if (Priority != Thread->Priority)\r
-    {\r
-        /* Reset the quantum and do the actual priority modification */\r
-        Thread->Quantum = Thread->QuantumReset;\r
-        KiSetPriorityThread(Thread, Priority, &Released);\r
-    }\r
-\r
-    /* Release thread lock */\r
-    KiReleaseThreadLock(Thread);\r
-\r
-    /* Check if lock was released */\r
-    if (!Released)\r
-    {\r
-        /* Release the dispatcher database */\r
-        KiReleaseDispatcherLock(OldIrql);\r
-    }\r
-    else\r
-    {\r
-        /* Lower IRQL only */\r
-        KeLowerIrql(OldIrql);\r
-    }\r
-\r
-    /* Return old increment */\r
-    return OldIncrement;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-KAFFINITY\r
-NTAPI\r
-KeSetAffinityThread(IN PKTHREAD Thread,\r
-                    IN KAFFINITY Affinity)\r
-{\r
-    KIRQL OldIrql;\r
-    KAFFINITY OldAffinity;\r
-    BOOLEAN Released;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the dispatcher database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Call the internal function */\r
-    OldAffinity = KiSetAffinityThread(Thread, Affinity, &Released);\r
-\r
-    /* Check if lock was released */\r
-    if (!Released)\r
-    {\r
-        /* Release the dispatcher database */\r
-        KiReleaseDispatcherLock(OldIrql);\r
-    }\r
-    else\r
-    {\r
-        /* Lower IRQL only */\r
-        KeLowerIrql(OldIrql);\r
-    }\r
-\r
-    /* Return old affinity */\r
-    return OldAffinity;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-KPRIORITY\r
-NTAPI\r
-KeSetPriorityThread(IN PKTHREAD Thread,\r
-                    IN KPRIORITY Priority)\r
-{\r
-    KIRQL OldIrql;\r
-    KPRIORITY OldPriority;\r
-    BOOLEAN Released;\r
-    ASSERT_THREAD(Thread);\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-    ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY));\r
-\r
-    /* Lock the Dispatcher Database */\r
-    OldIrql = KiAcquireDispatcherLock();\r
-\r
-    /* Lock the thread */\r
-    KiAcquireThreadLock(Thread);\r
-\r
-    /* Save the old Priority */\r
-    OldPriority = Thread->Priority;\r
-\r
-    /* Make sure that an actual change is being done */\r
-    if (OldPriority != Priority)\r
-    {\r
-        /* Reset the Quantum and Decrements */\r
-        Thread->Quantum = Thread->QuantumReset;\r
-        Thread->PriorityDecrement = 0;\r
-\r
-        /* Set the new Priority */\r
-        KiSetPriorityThread(Thread, Priority, &Released);\r
-    }\r
-\r
-    /* Release thread lock */\r
-    KiReleaseThreadLock(Thread);\r
-\r
-    /* Check if lock was released */\r
-    if (!Released)\r
-    {\r
-        /* Release the dispatcher database */\r
-        KiReleaseDispatcherLock(OldIrql);\r
-    }\r
-    else\r
-    {\r
-        /* Lower IRQL only */\r
-        KeLowerIrql(OldIrql);\r
-    }\r
-\r
-    /* Return Old Priority */\r
-    return OldPriority;\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-VOID\r
-NTAPI\r
-KeTerminateThread(IN KPRIORITY Increment)\r
-{\r
-    PLIST_ENTRY *ListHead;\r
-    PETHREAD Entry, SavedEntry;\r
-    PETHREAD *ThreadAddr;\r
-    KLOCK_QUEUE_HANDLE LockHandle;\r
-    PKTHREAD Thread = KeGetCurrentThread();\r
-    PKPROCESS Process = Thread->ApcState.Process;\r
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
-\r
-    /* Lock the process */\r
-    KiAcquireProcessLock(Process, &LockHandle);\r
-\r
-    /* Make sure we won't get Swapped */\r
-    KiSetThreadSwapBusy(Thread);\r
-\r
-    /* Save the Kernel and User Times */\r
-    Process->KernelTime += Thread->KernelTime;\r
-    Process->UserTime += Thread->UserTime;\r
-\r
-    /* Get the current entry and our Port */\r
-    Entry = (PETHREAD)PspReaperListHead.Flink;\r
-    ThreadAddr = &((PETHREAD)Thread)->ReaperLink;\r
-\r
-    /* Add it to the reaper's list */\r
-    do\r
-    {\r
-        /* Get the list head */\r
-        ListHead = &PspReaperListHead.Flink;\r
-\r
-        /* Link ourselves */\r
-        *ThreadAddr = Entry;\r
-        SavedEntry = Entry;\r
-\r
-        /* Now try to do the exchange */\r
-        Entry = InterlockedCompareExchangePointer(ListHead, ThreadAddr, Entry);\r
-\r
-        /* Break out if the change was succesful */\r
-    } while (Entry != SavedEntry);\r
-\r
-    /* Acquire the dispatcher lock */\r
-    KiAcquireDispatcherLockAtDpcLevel();\r
-\r
-    /* Check if the reaper wasn't active */\r
-    if (!Entry)\r
-    {\r
-        /* Activate it as a work item, directly through its Queue */\r
-        KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,\r
-                      &PspReaperWorkItem.List,\r
-                      FALSE);\r
-    }\r
-\r
-    /* Check the thread has an associated queue */\r
-    if (Thread->Queue)\r
-    {\r
-        /* Remove it from the list, and handle the queue */\r
-        RemoveEntryList(&Thread->QueueListEntry);\r
-        KiWakeQueue(Thread->Queue);\r
-    }\r
-\r
-    /* Signal the thread */\r
-    Thread->DispatcherHeader.SignalState = TRUE;\r
-    if (!IsListEmpty(&Thread->DispatcherHeader.WaitListHead))\r
-    {\r
-        /* Unwait the threads */\r
-        KxUnwaitThread(&Thread->DispatcherHeader, Increment);\r
-    }\r
-\r
-    /* Remove the thread from the list */\r
-    RemoveEntryList(&Thread->ThreadListEntry);\r
-\r
-    /* Release the process lock */\r
-    KiReleaseProcessLockFromDpcLevel(&LockHandle);\r
-\r
-    /* Set us as terminated, decrease the Process's stack count */\r
-    Thread->State = Terminated;\r
-\r
-    /* Decrease stack count */\r
-    ASSERT(Process->StackCount != 0);\r
-    ASSERT(Process->State == ProcessInMemory);\r
-    Process->StackCount--;\r
-    if (!Process->StackCount)\r
-    {\r
-        /* FIXME: Swap stacks */\r
-    }\r
-\r
-    /* Rundown arch-specific parts */\r
-    KiRundownThread(Thread);\r
-\r
-    /* Swap to a new thread */\r
-    KiReleaseDispatcherLockFromDpcLevel();\r
-    KiSwapThread(Thread, KeGetCurrentPrcb());\r
-}\r
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/ke/thrdobj.c
+ * PURPOSE:         Implements routines to manage the Kernel Thread Object
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
+extern LIST_ENTRY PspReaperListHead;
+
+ULONG KiMask32Array[MAXIMUM_PRIORITY] =
+{
+    0x1,        0x2,       0x4,       0x8,       0x10,       0x20,
+    0x40,       0x80,      0x100,     0x200,     0x4000,     0x800,
+    0x1000,     0x2000,    0x4000,    0x8000,    0x10000,    0x20000,
+    0x40000,    0x80000,   0x100000,  0x200000,  0x400000,   0x800000,
+    0x1000000,  0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,
+    0x40000000, 0x80000000
+};
+
+/* FUNCTIONS *****************************************************************/
+
+UCHAR
+NTAPI
+KeFindNextRightSetAffinity(IN UCHAR Number,
+                           IN ULONG Set)
+{
+    ULONG Bit, Result;
+    ASSERT(Set != 0);
+
+    /* Calculate the mask */
+    Bit = (AFFINITY_MASK(Number) - 1) & Set;
+
+    /* If it's 0, use the one we got */
+    if (!Bit) Bit = Set;
+
+    /* Now find the right set and return it */
+    BitScanReverse(&Result, Bit);
+    return (UCHAR)Result;
+}
+
+KPRIORITY
+NTAPI
+KeQueryBasePriorityThread(IN PKTHREAD Thread)
+{
+    LONG BaseIncrement;
+    KIRQL OldIrql;
+    PKPROCESS Process;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Raise IRQL to synch level */
+    OldIrql = KeRaiseIrqlToSynchLevel();
+
+    /* Lock the thread */
+    KiAcquireThreadLock(Thread);
+
+    /* Get the Process */
+    Process = Thread->ApcStatePointer[0]->Process;
+
+    /* Calculate the base increment */
+    BaseIncrement = Thread->BasePriority - Process->BasePriority;
+
+    /* If saturation occured, return the saturation increment instead */
+    if (Thread->Saturation) BaseIncrement = (HIGH_PRIORITY + 1) / 2 *
+                                            Thread->Saturation;
+
+    /* Release thread lock */
+    KiReleaseThreadLock(Thread);
+
+    /* Lower IRQl and return Increment */
+    KeLowerIrql(OldIrql);
+    return BaseIncrement;
+}
+
+VOID
+NTAPI
+KeReadyThread(IN PKTHREAD Thread)
+{
+    KIRQL OldIrql;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Make the thread ready */
+    KiReadyThread(Thread);
+
+    /* Unlock dispatcher database */
+    KiReleaseDispatcherLock(OldIrql);
+}
+
+ULONG
+NTAPI
+KeAlertResumeThread(IN PKTHREAD Thread)
+{
+    ULONG PreviousCount;
+    KLOCK_QUEUE_HANDLE ApcLock;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the Dispatcher Database and the APC Queue */
+    KiAcquireApcLock(Thread, &ApcLock);
+    KiAcquireDispatcherLockAtDpcLevel();
+
+    /* Return if Thread is already alerted. */
+    if (!Thread->Alerted[KernelMode])
+    {
+        /* If it's Blocked, unblock if it we should */
+        if ((Thread->State == Waiting) && (Thread->Alertable))
+        {
+            /* Abort the wait */
+            KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);
+        }
+        else
+        {
+            /* If not, simply Alert it */
+            Thread->Alerted[KernelMode] = TRUE;
+        }
+    }
+
+    /* Save the old Suspend Count */
+    PreviousCount = Thread->SuspendCount;
+
+    /* If the thread is suspended, decrease one of the suspend counts */
+    if (PreviousCount)
+    {
+        /* Decrease count. If we are now zero, unwait it completely */
+        Thread->SuspendCount--;
+        if (!(Thread->SuspendCount) && !(Thread->FreezeCount))
+        {
+            /* Signal and satisfy */
+            Thread->SuspendSemaphore.Header.SignalState++;
+            KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
+        }
+    }
+
+    /* Release Locks and return the Old State */
+    KiReleaseDispatcherLockFromDpcLevel();
+    KiReleaseApcLockFromDpcLevel(&ApcLock);
+    KiExitDispatcher(ApcLock.OldIrql);
+    return PreviousCount;
+}
+
+BOOLEAN
+NTAPI
+KeAlertThread(IN PKTHREAD Thread,
+              IN KPROCESSOR_MODE AlertMode)
+{
+    BOOLEAN PreviousState;
+    KLOCK_QUEUE_HANDLE ApcLock;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the Dispatcher Database and the APC Queue */
+    KiAcquireApcLock(Thread, &ApcLock);
+    KiAcquireDispatcherLockAtDpcLevel();
+
+    /* Save the Previous State */
+    PreviousState = Thread->Alerted[AlertMode];
+
+    /* Check if it's already alerted */
+    if (!PreviousState)
+    {
+        /* Check if the thread is alertable, and blocked in the given mode */
+        if ((Thread->State == Waiting) &&
+            (Thread->Alertable) &&
+            (AlertMode <= Thread->WaitMode))
+        {
+            /* Abort the wait to alert the thread */
+            KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);
+        }
+        else
+        {
+            /* Otherwise, merely set the alerted state */
+            Thread->Alerted[AlertMode] = TRUE;
+        }
+    }
+
+    /* Release the Dispatcher Lock */
+    KiReleaseDispatcherLockFromDpcLevel();
+    KiReleaseApcLockFromDpcLevel(&ApcLock);
+    KiExitDispatcher(ApcLock.OldIrql);
+
+    /* Return the old state */
+    return PreviousState;
+}
+
+ULONG
+NTAPI
+KeForceResumeThread(IN PKTHREAD Thread)
+{
+    KLOCK_QUEUE_HANDLE ApcLock;
+    ULONG PreviousCount;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the APC Queue */
+    KiAcquireApcLock(Thread, &ApcLock);
+
+    /* Save the old Suspend Count */
+    PreviousCount = Thread->SuspendCount + Thread->FreezeCount;
+
+    /* If the thread is suspended, wake it up!!! */
+    if (PreviousCount)
+    {
+        /* Unwait it completely */
+        Thread->SuspendCount = 0;
+        Thread->FreezeCount = 0;
+
+        /* Lock the dispatcher */
+        KiAcquireDispatcherLockAtDpcLevel();
+
+        /* Signal and satisfy */
+        Thread->SuspendSemaphore.Header.SignalState++;
+        KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
+
+        /* Release the dispatcher */
+        KiReleaseDispatcherLockFromDpcLevel();
+    }
+
+    /* Release Lock and return the Old State */
+    KiReleaseApcLockFromDpcLevel(&ApcLock);
+    KiExitDispatcher(ApcLock.OldIrql);
+    return PreviousCount;
+}
+
+VOID
+NTAPI
+KeFreezeAllThreads(VOID)
+{
+    KLOCK_QUEUE_HANDLE LockHandle, ApcLock;
+    PKTHREAD Current, CurrentThread = KeGetCurrentThread();
+    PKPROCESS Process = CurrentThread->ApcState.Process;
+    PLIST_ENTRY ListHead, NextEntry;
+    LONG OldCount;
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the process */
+    KiAcquireProcessLock(Process, &LockHandle);
+
+    /* If someone is already trying to free us, try again */
+    while (CurrentThread->FreezeCount)
+    {
+        /* Release and re-acquire the process lock so the APC will go through */
+        KiReleaseProcessLock(&LockHandle);
+        KiAcquireProcessLock(Process, &LockHandle);
+    }
+
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
+
+    /* Loop the Process's Threads */
+    ListHead = &Process->ThreadListHead;
+    NextEntry = ListHead->Flink;
+    do
+    {
+        /* Get the current thread */
+        Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
+
+        /* Lock it */
+        KiAcquireApcLockAtDpcLevel(Current, &ApcLock);
+
+        /* Make sure it's not ours, and check if APCs are enabled */
+        if ((Current != CurrentThread) && (Current->ApcQueueable))
+        {
+            /* Sanity check */
+            OldCount = Current->SuspendCount;
+            ASSERT(OldCount != MAXIMUM_SUSPEND_COUNT);
+
+            /* Increase the freeze count */
+            Current->FreezeCount++;
+
+            /* Make sure it wasn't already suspended */
+            if (!(OldCount) && !(Current->SuspendCount))
+            {
+                /* Did we already insert it? */
+                if (!Current->SuspendApc.Inserted)
+                {
+                    /* Insert the APC */
+                    Current->SuspendApc.Inserted = TRUE;
+                    KiInsertQueueApc(&Current->SuspendApc, IO_NO_INCREMENT);
+                }
+                else
+                {
+                    /* Lock the dispatcher */
+                    KiAcquireDispatcherLockAtDpcLevel();
+
+                    /* Unsignal the semaphore, the APC was already inserted */
+                    Current->SuspendSemaphore.Header.SignalState--;
+
+                    /* Release the dispatcher */
+                    KiReleaseDispatcherLockFromDpcLevel();
+                }
+            }
+        }
+
+        /* Release the APC lock */
+        KiReleaseApcLockFromDpcLevel(&ApcLock);
+
+        /* Move to the next thread */
+        NextEntry = NextEntry->Flink;
+    } while (NextEntry != ListHead);
+
+    /* Release the process lock and exit the dispatcher */
+    KiReleaseProcessLock(&LockHandle);
+    KiExitDispatcher(LockHandle.OldIrql);
+}
+
+ULONG
+NTAPI
+KeResumeThread(IN PKTHREAD Thread)
+{
+    KLOCK_QUEUE_HANDLE ApcLock;
+    ULONG PreviousCount;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the APC Queue */
+    KiAcquireApcLock(Thread, &ApcLock);
+
+    /* Save the Old Count */
+    PreviousCount = Thread->SuspendCount;
+
+    /* Check if it existed */
+    if (PreviousCount)
+    {
+        /* Decrease the suspend count */
+        Thread->SuspendCount--;
+
+        /* Check if the thrad is still suspended or not */
+        if ((!Thread->SuspendCount) && (!Thread->FreezeCount))
+        {
+            /* Acquire the dispatcher lock */
+            KiAcquireDispatcherLockAtDpcLevel();
+
+            /* Signal the Suspend Semaphore */
+            Thread->SuspendSemaphore.Header.SignalState++;
+            KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
+
+            /* Release the dispatcher lock */
+            KiReleaseDispatcherLockFromDpcLevel();
+        }
+    }
+
+    /* Release APC Queue lock and return the Old State */
+    KiReleaseApcLockFromDpcLevel(&ApcLock);
+    KiExitDispatcher(ApcLock.OldIrql);
+    return PreviousCount;
+}
+
+VOID
+NTAPI
+KeRundownThread(VOID)
+{
+    KIRQL OldIrql;
+    PKTHREAD Thread = KeGetCurrentThread();
+    PLIST_ENTRY NextEntry, ListHead;
+    PKMUTANT Mutant;
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Optimized path if nothing is on the list at the moment */
+    if (IsListEmpty(&Thread->MutantListHead)) return;
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Get the List Pointers */
+    ListHead = &Thread->MutantListHead;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the Mutant */
+        Mutant = CONTAINING_RECORD(NextEntry, KMUTANT, MutantListEntry);
+
+        /* Make sure it's not terminating with APCs off */
+        if (Mutant->ApcDisable)
+        {
+            /* Bugcheck the system */
+            KEBUGCHECKEX(0, //THREAD_TERMINATE_HELD_MUTEX,
+                         (ULONG_PTR)Thread,
+                         (ULONG_PTR)Mutant,
+                         0,
+                         0);
+        }
+
+        /* Now we can remove it */
+        RemoveEntryList(&Mutant->MutantListEntry);
+
+        /* Unconditionally abandon it */
+        Mutant->Header.SignalState = 1;
+        Mutant->Abandoned = TRUE;
+        Mutant->OwnerThread = NULL;
+
+        /* Check if the Wait List isn't empty */
+        if (!IsListEmpty(&Mutant->Header.WaitListHead))
+        {
+            /* Wake the Mutant */
+            KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);
+        }
+
+        /* Move on */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Release the Lock */
+    KiReleaseDispatcherLock(OldIrql);
+}
+
+VOID
+NTAPI
+KeStartThread(IN OUT PKTHREAD Thread)
+{
+    KLOCK_QUEUE_HANDLE LockHandle;
+#ifdef CONFIG_SMP
+    PKNODE Node;
+    PKPRCB NodePrcb;
+    ULONG Set, Mask;
+#endif
+    UCHAR IdealProcessor = 0;
+    PKPROCESS Process = Thread->ApcState.Process;
+
+    /* Setup static fields from parent */
+    Thread->DisableBoost = Process->DisableBoost;
+    Thread->Iopl = Process->Iopl;
+    Thread->Quantum = Process->QuantumReset;
+    Thread->QuantumReset = Process->QuantumReset;
+    Thread->SystemAffinityActive = FALSE;
+
+    /* Lock the process */
+    KiAcquireProcessLock(Process, &LockHandle);
+
+    /* Setup volatile data */
+    Thread->Priority = Process->BasePriority;
+    Thread->BasePriority = Process->BasePriority;
+    Thread->Affinity = Process->Affinity;
+    Thread->UserAffinity = Process->Affinity;
+
+#ifdef CONFIG_SMP
+    /* Get the KNODE and its PRCB */
+    Node = KeNodeBlock[Process->IdealNode];
+    NodePrcb = (PKPRCB)(KPCR_BASE + (Process->ThreadSeed * PAGE_SIZE));
+
+    /* Calculate affinity mask */
+    Set = ~NodePrcb->MultiThreadProcessorSet;
+    Mask = (ULONG)(Node->ProcessorMask & Process->Affinity);
+    Set &= Mask;
+    if (Set) Mask = Set;
+
+    /* Get the new thread seed */
+    IdealProcessor = KeFindNextRightSetAffinity(Process->ThreadSeed, Mask);
+    Process->ThreadSeed = IdealProcessor;
+
+    /* Sanity check */
+    ASSERT((Thread->UserAffinity & AFFINITY_MASK(IdealProcessor)));
+#endif
+
+    /* Set the Ideal Processor */
+    Thread->IdealProcessor = IdealProcessor;
+    Thread->UserIdealProcessor = IdealProcessor;
+
+    /* Lock the Dispatcher Database */
+    KiAcquireDispatcherLockAtDpcLevel();
+
+    /* Insert the thread into the process list */
+    InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
+
+    /* Increase the stack count */
+    ASSERT(Process->StackCount != MAXULONG_PTR);
+    Process->StackCount++;
+
+    /* Release locks and return */
+    KiReleaseDispatcherLockFromDpcLevel();
+    KiReleaseProcessLock(&LockHandle);
+}
+
+VOID
+NTAPI
+KiSuspendRundown(IN PKAPC Apc)
+{
+    /* Does nothing */
+    UNREFERENCED_PARAMETER(Apc);
+}
+
+VOID
+NTAPI
+KiSuspendNop(IN PKAPC Apc,
+             IN PKNORMAL_ROUTINE *NormalRoutine,
+             IN PVOID *NormalContext,
+             IN PVOID *SystemArgument1,
+             IN PVOID *SystemArgument2)
+{
+    /* Does nothing */
+    UNREFERENCED_PARAMETER(Apc);
+    UNREFERENCED_PARAMETER(NormalRoutine);
+    UNREFERENCED_PARAMETER(NormalContext);
+    UNREFERENCED_PARAMETER(SystemArgument1);
+    UNREFERENCED_PARAMETER(SystemArgument2);
+}
+
+VOID
+NTAPI
+KiSuspendThread(IN PVOID NormalContext,
+                IN PVOID SystemArgument1,
+                IN PVOID SystemArgument2)
+{
+    /* Non-alertable kernel-mode suspended wait */
+    KeWaitForSingleObject(&KeGetCurrentThread()->SuspendSemaphore,
+                          Suspended,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+}
+
+NTSTATUS
+NTAPI
+KeSuspendThread(PKTHREAD Thread)
+{
+    KLOCK_QUEUE_HANDLE ApcLock;
+    ULONG PreviousCount;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the APC Queue */
+    KiAcquireApcLock(Thread, &ApcLock);
+
+    /* Save the Old Count */
+    PreviousCount = Thread->SuspendCount;
+
+    /* Handle the maximum */
+    if (PreviousCount == MAXIMUM_SUSPEND_COUNT)
+    {
+        /* Raise an exception */
+        KiReleaseApcLock(&ApcLock);
+        RtlRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
+    }
+
+    /* Should we bother to queue at all? */
+    if (Thread->ApcQueueable)
+    {
+        /* Increment the suspend count */
+        Thread->SuspendCount++;
+
+        /* Check if we should suspend it */
+        if (!(PreviousCount) && !(Thread->FreezeCount))
+        {
+            /* Is the APC already inserted? */
+            if (!Thread->SuspendApc.Inserted)
+            {
+                /* Not inserted, insert it */
+                Thread->SuspendApc.Inserted = TRUE;
+                KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT);
+            }
+            else
+            {
+                /* Lock the dispatcher */
+                KiAcquireDispatcherLockAtDpcLevel();
+
+                /* Unsignal the semaphore, the APC was already inserted */
+                Thread->SuspendSemaphore.Header.SignalState--;
+
+                /* Release the dispatcher */
+                KiReleaseDispatcherLockFromDpcLevel();
+            }
+        }
+    }
+
+    /* Release Lock and return the Old State */
+    KiReleaseApcLockFromDpcLevel(&ApcLock);
+    KiExitDispatcher(ApcLock.OldIrql);
+    return PreviousCount;
+}
+
+VOID
+NTAPI
+KeThawAllThreads(VOID)
+{
+    KLOCK_QUEUE_HANDLE LockHandle, ApcLock;
+    PKTHREAD Current, CurrentThread = KeGetCurrentThread();
+    PKPROCESS Process = CurrentThread->ApcState.Process;
+    PLIST_ENTRY ListHead, NextEntry;
+    LONG OldCount;
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the process */
+    KiAcquireProcessLock(Process, &LockHandle);
+
+    /* Loop the Process's Threads */
+    ListHead = &Process->ThreadListHead;
+    NextEntry = ListHead->Flink;
+    do
+    {
+        /* Get the current thread */
+        Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
+
+        /* Lock it */
+        KiAcquireApcLockAtDpcLevel(Current, &ApcLock);
+
+        /* Make sure we are frozen */
+        OldCount = Current->FreezeCount;
+        if (OldCount)
+        {
+            /* Decrease the freeze count */
+            Current->FreezeCount--;
+
+            /* Check if both counts are zero now */
+            if (!(Current->SuspendCount) && (!Current->FreezeCount))
+            {
+                /* Lock the dispatcher */
+                KiAcquireDispatcherLockAtDpcLevel();
+
+                /* Signal the suspend semaphore and wake it */
+                Current->SuspendSemaphore.Header.SignalState++;
+                KiWaitTest(&Current->SuspendSemaphore, 1);
+
+                /* Unlock the dispatcher */
+                KiReleaseDispatcherLockFromDpcLevel();
+            }
+        }
+
+        /* Release the APC lock */
+        KiReleaseApcLockFromDpcLevel(&ApcLock);
+
+        /* Go to the next one */
+        NextEntry = NextEntry->Flink;
+    } while (NextEntry != ListHead);
+
+    /* Release the process lock and exit the dispatcher */
+    KiReleaseProcessLock(&LockHandle);
+    KiExitDispatcher(LockHandle.OldIrql);
+
+    /* Leave the critical region */
+    KeLeaveCriticalRegion();
+}
+
+BOOLEAN
+NTAPI
+KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
+{
+    PKTHREAD Thread = KeGetCurrentThread();
+    BOOLEAN OldState;
+    KLOCK_QUEUE_HANDLE ApcLock;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the Dispatcher Database and the APC Queue */
+    KiAcquireApcLock(Thread, &ApcLock);
+
+    /* Save the old State */
+    OldState = Thread->Alerted[AlertMode];
+
+    /* Check the Thread is alerted */
+    if (OldState)
+    {
+        /* Disable alert for this mode */
+        Thread->Alerted[AlertMode] = FALSE;
+    }
+    else if ((AlertMode != KernelMode) &&
+             (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
+    {
+        /* If the mode is User and the Queue isn't empty, set Pending */
+        Thread->ApcState.UserApcPending = TRUE;
+    }
+
+    /* Release Locks and return the Old State */
+    KiReleaseApcLock(&ApcLock);
+    return OldState;
+}
+
+NTSTATUS
+NTAPI
+KeInitThread(IN OUT PKTHREAD Thread,
+             IN PVOID KernelStack,
+             IN PKSYSTEM_ROUTINE SystemRoutine,
+             IN PKSTART_ROUTINE StartRoutine,
+             IN PVOID StartContext,
+             IN PCONTEXT Context,
+             IN PVOID Teb,
+             IN PKPROCESS Process)
+{
+    BOOLEAN AllocatedStack = FALSE;
+    ULONG i;
+    PKWAIT_BLOCK TimerWaitBlock;
+    PKTIMER Timer;
+    NTSTATUS Status;
+
+    /* Initalize the Dispatcher Header */
+    KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
+                                 ThreadObject,
+                                 sizeof(KTHREAD) / sizeof(LONG),
+                                 FALSE);
+
+    /* Initialize the Mutant List */
+    InitializeListHead(&Thread->MutantListHead);
+
+    /* Initialize the wait blocks */
+    for (i = 0; i< (THREAD_WAIT_OBJECTS + 1); i++)
+    {
+        /* Put our pointer */
+        Thread->WaitBlock[i].Thread = Thread;
+    }
+
+    /* Set swap settings */
+    Thread->EnableStackSwap = FALSE;//TRUE;
+    Thread->IdealProcessor = 1;
+    Thread->SwapBusy = FALSE;
+    Thread->KernelStackResident = TRUE;
+    Thread->AdjustReason = AdjustNone;
+
+    /* Initialize the lock */
+    KeInitializeSpinLock(&Thread->ThreadLock);
+
+    /* Setup the Service Descriptor Table for Native Calls */
+    Thread->ServiceTable = KeServiceDescriptorTable;
+
+    /* Setup APC Fields */
+    InitializeListHead(&Thread->ApcState.ApcListHead[0]);
+    InitializeListHead(&Thread->ApcState.ApcListHead[1]);
+    Thread->ApcState.Process = Process;
+    Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
+    Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
+    Thread->ApcStateIndex = OriginalApcEnvironment;
+    Thread->ApcQueueable = TRUE;
+    KeInitializeSpinLock(&Thread->ApcQueueLock);
+
+    /* Initialize the Suspend APC */
+    KeInitializeApc(&Thread->SuspendApc,
+                    Thread,
+                    OriginalApcEnvironment,
+                    KiSuspendNop,
+                    KiSuspendRundown,
+                    KiSuspendThread,
+                    KernelMode,
+                    NULL);
+
+    /* Initialize the Suspend Semaphore */
+    KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 2);
+
+    /* Setup the timer */
+    Timer = &Thread->Timer;
+    KeInitializeTimer(Timer);
+    TimerWaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
+    TimerWaitBlock->Object = Timer;
+    TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
+    TimerWaitBlock->WaitType = WaitAny;
+    TimerWaitBlock->NextWaitBlock = NULL;
+
+    /* Link the two wait lists together */
+    TimerWaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead;
+    TimerWaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead;
+
+    /* Set the TEB */
+    Thread->Teb = Teb;
+
+    /* Check if we have a kernel stack */
+    if (!KernelStack)
+    {
+        /* We don't, allocate one */
+        KernelStack = (PVOID)((ULONG_PTR)MmCreateKernelStack(FALSE) +
+                              KERNEL_STACK_SIZE);
+        if (!KernelStack) return STATUS_INSUFFICIENT_RESOURCES;
+
+        /* Remember for later */
+        AllocatedStack = TRUE;
+    }
+
+    /* Set the Thread Stacks */
+    Thread->InitialStack = (PCHAR)KernelStack;
+    Thread->StackBase = (PCHAR)KernelStack;
+    Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;
+    Thread->KernelStackResident = TRUE;
+
+    /* ROS Mm HACK */
+    MmUpdatePageDir((PEPROCESS)Process,
+                    (PVOID)Thread->StackLimit,
+                    KERNEL_STACK_SIZE);
+    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
+
+    /* Enter SEH to avoid crashes due to user mode */
+    Status = STATUS_SUCCESS;
+    _SEH_TRY
+    {
+        /* Initalize the Thread Context */
+        Ke386InitThreadWithContext(Thread,
+                                   SystemRoutine,
+                                   StartRoutine,
+                                   StartContext,
+                                   Context);
+    }
+    _SEH_HANDLE
+    {
+        /* Set failure status */
+        Status = STATUS_UNSUCCESSFUL;
+
+        /* Check if a stack was allocated */
+        if (AllocatedStack)
+        {
+            /* Delete the stack */
+            MmDeleteKernelStack(Thread->StackBase, FALSE);
+            Thread->InitialStack = NULL;
+        }
+    }
+    _SEH_END;
+
+    /* Set the Thread to initalized */
+    Thread->State = Initialized;
+    return Status;
+}
+
+VOID
+NTAPI
+KeInitializeThread(IN PKPROCESS Process,
+                   IN OUT PKTHREAD Thread,
+                   IN PKSYSTEM_ROUTINE SystemRoutine,
+                   IN PKSTART_ROUTINE StartRoutine,
+                   IN PVOID StartContext,
+                   IN PCONTEXT Context,
+                   IN PVOID Teb,
+                   IN PVOID KernelStack)
+{
+    /* Initailize and start the thread on success */
+    if (NT_SUCCESS(KeInitThread(Thread,
+                                KernelStack,
+                                SystemRoutine,
+                                StartRoutine,
+                                StartContext,
+                                Context,
+                                Teb,
+                                Process)))
+    {
+        /* Start it */
+        KeStartThread(Thread);
+    }
+}
+
+VOID
+NTAPI
+KeUninitThread(IN PKTHREAD Thread)
+{
+    /* Delete the stack */
+    MmDeleteKernelStack(Thread->StackBase, FALSE);
+    Thread->InitialStack = NULL;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @unimplemented
+ */
+VOID
+NTAPI
+KeCapturePersistentThreadState(IN PVOID CurrentThread,
+                               IN ULONG Setting1,
+                               IN ULONG Setting2,
+                               IN ULONG Setting3,
+                               IN ULONG Setting4,
+                               IN ULONG Setting5,
+                               IN PVOID ThreadState)
+{
+    UNIMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+#undef KeGetCurrentThread
+PKTHREAD
+NTAPI
+KeGetCurrentThread(VOID)
+{
+    /* Return the current thread on this PCR */
+    return _KeGetCurrentThread();
+}
+
+/*
+ * @implemented
+ */
+#undef KeGetPreviousMode
+UCHAR
+NTAPI
+KeGetPreviousMode(VOID)
+{
+    /* Return the previous mode of this thread */
+    return _KeGetPreviousMode();
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+KeQueryRuntimeThread(IN PKTHREAD Thread,
+                     OUT PULONG UserTime)
+{
+    ASSERT_THREAD(Thread);
+
+    /* Return the User Time */
+    *UserTime = Thread->UserTime;
+
+    /* Return the Kernel Time */
+    return Thread->KernelTime;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
+{
+    BOOLEAN PreviousState;
+    PKTHREAD Thread = KeGetCurrentThread();
+
+    /* Save Old State */
+    PreviousState = Thread->EnableStackSwap;
+
+    /* Set New State */
+    Thread->EnableStackSwap = Enable;
+
+    /* Return Old State */
+    return PreviousState;
+}
+
+/*
+ * @implemented
+ */
+KPRIORITY
+NTAPI
+KeQueryPriorityThread(IN PKTHREAD Thread)
+{
+    ASSERT_THREAD(Thread);
+
+    /* Return the current priority */
+    return Thread->Priority;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeRevertToUserAffinityThread(VOID)
+{
+    KIRQL OldIrql;
+    PKPRCB Prcb;
+    PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+    ASSERT(CurrentThread->SystemAffinityActive != FALSE);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Set the user affinity and processor and disable system affinity */
+    CurrentThread->Affinity = CurrentThread->UserAffinity;
+    CurrentThread->IdealProcessor = CurrentThread->UserIdealProcessor;
+    CurrentThread->SystemAffinityActive = FALSE;
+
+    /* Get the current PRCB and check if it doesn't match this affinity */
+    Prcb = KeGetCurrentPrcb();
+    if (!(Prcb->SetMember & CurrentThread->Affinity))
+    {
+        /* Lock the PRCB */
+        KiAcquirePrcbLock(Prcb);
+
+#ifdef NEW_SCHEDULER
+        /* Check if there's no next thread scheduled */
+        if (!Prcb->NextThread)
+        {
+            /* Select a new thread and set it on standby */
+            NextThread = KiSelectNextThread(Prcb);
+            NextThread->State = Standby;
+            Prcb->NextThread = NextThread;
+        }
+#else
+        /* We need to dispatch a new thread */
+        NextThread = NULL;
+        CurrentThread->WaitIrql = OldIrql;
+        KiDispatchThreadNoLock(Ready);
+        KeLowerIrql(OldIrql);
+        return;
+#endif
+
+        /* Release the PRCB lock */
+        KiReleasePrcbLock(Prcb);
+    }
+
+    /* Unlock dispatcher database */
+    KiReleaseDispatcherLock(OldIrql);
+}
+
+/*
+ * @implemented
+ */
+UCHAR
+NTAPI
+KeSetIdealProcessorThread(IN PKTHREAD Thread,
+                          IN UCHAR Processor)
+{
+    CCHAR OldIdealProcessor;
+    KIRQL OldIrql;
+    ASSERT(Processor <= MAXIMUM_PROCESSORS);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Save Old Ideal Processor */
+    OldIdealProcessor = Thread->UserIdealProcessor;
+
+    /* Make sure a valid CPU was given */
+    if (Processor < KeNumberProcessors)
+    {
+        /* Check if the user ideal CPU is in the affinity */
+        if (Thread->Affinity & AFFINITY_MASK(Processor))
+        {
+            /* Set the ideal processor */
+            Thread->IdealProcessor = Processor;
+
+            /* Check if system affinity is used */
+            if (!Thread->SystemAffinityActive)
+            {
+                /* It's not, so update the user CPU too */
+                Thread->UserIdealProcessor = Processor;
+            }
+        }
+    }
+
+    /* Release dispatcher lock and return the old ideal CPU */
+    KiReleaseDispatcherLock(OldIrql);
+    return OldIdealProcessor;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeSetSystemAffinityThread(IN KAFFINITY Affinity)
+{
+    KIRQL OldIrql;
+    PKPRCB Prcb;
+    PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+    ASSERT((Affinity & KeActiveProcessors) != 0);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Restore the affinity and enable system affinity */
+    CurrentThread->Affinity = Affinity;
+    CurrentThread->SystemAffinityActive = TRUE;
+
+    /* Check if the ideal processor is part of the affinity */
+#ifdef CONFIG_SMP
+    if (!(Affinity & AFFINITY_MASK(CurrentThread->IdealProcessor)))
+    {
+        ULONG AffinitySet, NodeMask;
+
+        /* It's not! Get the PRCB */
+        Prcb = KiProcessorBlock[CurrentThread->IdealProcessor];
+
+        /* Calculate the affinity set */
+        AffinitySet = KeActiveProcessors & Affinity;
+        NodeMask = Prcb->ParentNode->ProcessorMask & AffinitySet;
+        if (NodeMask)
+        {
+            /* Use the Node set instead */
+            AffinitySet = NodeMask;
+        }
+
+        /* Calculate the ideal CPU from the affinity set */
+        BitScanReverse(&NodeMask, AffinitySet);
+        CurrentThread->IdealProcessor = (UCHAR)NodeMask;
+    }
+#endif
+
+    /* Get the current PRCB and check if it doesn't match this affinity */
+    Prcb = KeGetCurrentPrcb();
+    if (!(Prcb->SetMember & CurrentThread->Affinity))
+    {
+        /* Lock the PRCB */
+        KiAcquirePrcbLock(Prcb);
+
+#ifdef NEW_SCHEDULER
+        /* Check if there's no next thread scheduled */
+        if (!Prcb->NextThread)
+        {
+            /* Select a new thread and set it on standby */
+            NextThread = KiSelectNextThread(Prcb);
+            NextThread->State = Standby;
+            Prcb->NextThread = NextThread;
+        }
+#else
+        /* We need to dispatch a new thread */
+        NextThread = NULL;
+        CurrentThread->WaitIrql = OldIrql;
+        KiDispatchThreadNoLock(Ready);
+        KeLowerIrql(OldIrql);
+        return;
+#endif
+
+        /* Release the PRCB lock */
+        KiReleasePrcbLock(Prcb);
+    }
+
+    /* Unlock dispatcher database */
+    KiReleaseDispatcherLock(OldIrql);
+}
+
+/*
+ * @implemented
+ */
+LONG
+NTAPI
+KeSetBasePriorityThread(IN PKTHREAD Thread,
+                        IN LONG Increment)
+{
+    KIRQL OldIrql;
+    KPRIORITY OldBasePriority, Priority, BasePriority;
+    LONG OldIncrement;
+    PKPROCESS Process;
+    BOOLEAN Released = FALSE;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Get the process */
+    Process = Thread->ApcState.Process;
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Lock the thread */
+    KiAcquireThreadLock(Thread);
+
+    /* Save the old base priority and increment */
+    OldBasePriority = Thread->BasePriority;
+    OldIncrement = OldBasePriority - Process->BasePriority;
+
+    /* If priority saturation happened, use the saturated increment */
+    if (Thread->Saturation) OldIncrement = (HIGH_PRIORITY + 1) / 2 *
+                                            Thread->Saturation;
+
+    /* Now check if saturation is being used for the new value */
+    if (abs(Increment) >= ((HIGH_PRIORITY + 1) / 2))
+    {
+        /* Check if we need positive or negative saturation */
+        Thread->Saturation = (Increment > 0) ? 1 : -1;
+    }
+
+    /* Normalize the Base Priority */
+    BasePriority = Process->BasePriority + Increment;
+    if (Process->BasePriority >= LOW_REALTIME_PRIORITY)
+    {
+        /* Check if it's too low */
+        if (BasePriority < LOW_REALTIME_PRIORITY)
+        {
+            /* Set it to the lowest real time level */
+            BasePriority = LOW_REALTIME_PRIORITY;
+        }
+
+        /* Check if it's too high */
+        if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;
+
+        /* We are at real time, so use the raw base priority */
+        Priority = BasePriority;
+    }
+    else
+    {
+        /* Check if it's entering the real time range */
+        if (BasePriority >= LOW_REALTIME_PRIORITY)
+        {
+            /* Set it to the highest dynamic level */
+            BasePriority = LOW_REALTIME_PRIORITY - 1;
+        }
+
+        /* Check if it's too low and normalize it */
+        if (BasePriority <= LOW_PRIORITY) BasePriority = 1;
+
+        /* Check if Saturation is used */
+        if (Thread->Saturation)
+        {
+            /* Use the raw base priority */
+            Priority = BasePriority;
+        }
+        else
+        {
+            /* Otherwise, calculate the new priority */
+            Priority = KiComputeNewPriority(Thread, 0);
+            Priority += (BasePriority - OldBasePriority);
+
+            /* Check if it entered the real-time range */
+            if (Priority >= LOW_REALTIME_PRIORITY)
+            {
+                /* Normalize it down to the highest dynamic priority */
+                Priority = LOW_REALTIME_PRIORITY - 1;
+            }
+            else if (Priority <= LOW_PRIORITY)
+            {
+                /* It went too low, normalize it */
+                Priority = 1;
+            }
+        }
+    }
+
+    /* Finally set the new base priority */
+    Thread->BasePriority = (SCHAR)BasePriority;
+
+    /* Reset the decrements */
+    Thread->PriorityDecrement = 0;
+
+    /* Check if we're changing priority after all */
+    if (Priority != Thread->Priority)
+    {
+        /* Reset the quantum and do the actual priority modification */
+        Thread->Quantum = Thread->QuantumReset;
+        KiSetPriorityThread(Thread, Priority, &Released);
+    }
+
+    /* Release thread lock */
+    KiReleaseThreadLock(Thread);
+
+    /* Check if lock was released */
+    if (!Released)
+    {
+        /* Release the dispatcher database */
+        KiReleaseDispatcherLock(OldIrql);
+    }
+    else
+    {
+        /* Lower IRQL only */
+        KeLowerIrql(OldIrql);
+    }
+
+    /* Return old increment */
+    return OldIncrement;
+}
+
+/*
+ * @implemented
+ */
+KAFFINITY
+NTAPI
+KeSetAffinityThread(IN PKTHREAD Thread,
+                    IN KAFFINITY Affinity)
+{
+    KIRQL OldIrql;
+    KAFFINITY OldAffinity;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the dispatcher database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Call the internal function */
+    OldAffinity = KiSetAffinityThread(Thread, Affinity);
+
+    /* Release the dispatcher database and return old affinity */
+    KiReleaseDispatcherLock(OldIrql);
+    return OldAffinity;
+}
+
+/*
+ * @implemented
+ */
+KPRIORITY
+NTAPI
+KeSetPriorityThread(IN PKTHREAD Thread,
+                    IN KPRIORITY Priority)
+{
+    KIRQL OldIrql;
+    KPRIORITY OldPriority;
+    BOOLEAN Released = FALSE;
+    ASSERT_THREAD(Thread);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+    ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY));
+    ASSERT(KeIsExecutingDpc() == FALSE);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KiAcquireDispatcherLock();
+
+    /* Lock the thread */
+    KiAcquireThreadLock(Thread);
+
+    /* Save the old Priority and reset decrement */
+    OldPriority = Thread->Priority;
+    Thread->PriorityDecrement = 0;
+
+    /* Make sure that an actual change is being done */
+    if (Priority != Thread->Priority)
+    {
+        /* Reset the quantum */
+        Thread->Quantum = Thread->QuantumReset;
+
+        /* Check if priority is being set too low and normalize if so */
+        if ((Thread->BasePriority != 0) && !(Priority)) Priority = 1;
+
+        /* Set the new Priority */
+        KiSetPriorityThread(Thread, Priority, &Released);
+    }
+
+    /* Release thread lock */
+    KiReleaseThreadLock(Thread);
+
+    /* Check if lock was released */
+    if (!Released)
+    {
+        /* Release the dispatcher database */
+        KiReleaseDispatcherLock(OldIrql);
+    }
+    else
+    {
+        /* Lower IRQL only */
+        KeLowerIrql(OldIrql);
+    }
+
+    /* Return Old Priority */
+    return OldPriority;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeTerminateThread(IN KPRIORITY Increment)
+{
+    PLIST_ENTRY *ListHead;
+    PETHREAD Entry, SavedEntry;
+    PETHREAD *ThreadAddr;
+    KLOCK_QUEUE_HANDLE LockHandle;
+    PKTHREAD Thread = KeGetCurrentThread();
+    PKPROCESS Process = Thread->ApcState.Process;
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+    /* Lock the process */
+    KiAcquireProcessLock(Process, &LockHandle);
+
+    /* Make sure we won't get Swapped */
+    KiSetThreadSwapBusy(Thread);
+
+    /* Save the Kernel and User Times */
+    Process->KernelTime += Thread->KernelTime;
+    Process->UserTime += Thread->UserTime;
+
+    /* Get the current entry and our Port */
+    Entry = (PETHREAD)PspReaperListHead.Flink;
+    ThreadAddr = &((PETHREAD)Thread)->ReaperLink;
+
+    /* Add it to the reaper's list */
+    do
+    {
+        /* Get the list head */
+        ListHead = &PspReaperListHead.Flink;
+
+        /* Link ourselves */
+        *ThreadAddr = Entry;
+        SavedEntry = Entry;
+
+        /* Now try to do the exchange */
+        Entry = InterlockedCompareExchangePointer(ListHead, ThreadAddr, Entry);
+
+        /* Break out if the change was succesful */
+    } while (Entry != SavedEntry);
+
+    /* Acquire the dispatcher lock */
+    KiAcquireDispatcherLockAtDpcLevel();
+
+    /* Check if the reaper wasn't active */
+    if (!Entry)
+    {
+        /* Activate it as a work item, directly through its Queue */
+        KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,
+                      &PspReaperWorkItem.List,
+                      FALSE);
+    }
+
+    /* Check the thread has an associated queue */
+    if (Thread->Queue)
+    {
+        /* Remove it from the list, and handle the queue */
+        RemoveEntryList(&Thread->QueueListEntry);
+        KiActivateWaiterQueue(Thread->Queue);
+    }
+
+    /* Signal the thread */
+    Thread->DispatcherHeader.SignalState = TRUE;
+    if (!IsListEmpty(&Thread->DispatcherHeader.WaitListHead))
+    {
+        /* Unwait the threads */
+        KxUnwaitThread(&Thread->DispatcherHeader, Increment);
+    }
+
+    /* Remove the thread from the list */
+    RemoveEntryList(&Thread->ThreadListEntry);
+
+    /* Release the process lock */
+    KiReleaseProcessLockFromDpcLevel(&LockHandle);
+
+    /* Set us as terminated, decrease the Process's stack count */
+    Thread->State = Terminated;
+
+    /* Decrease stack count */
+    ASSERT(Process->StackCount != 0);
+    ASSERT(Process->State == ProcessInMemory);
+    Process->StackCount--;
+    if (!(Process->StackCount) && !(IsListEmpty(&Process->ThreadListHead)))
+    {
+        /* FIXME: Swap stacks */
+    }
+
+    /* Rundown arch-specific parts */
+    KiRundownThread(Thread);
+
+    /* Swap to a new thread */
+    KiReleaseDispatcherLockFromDpcLevel();
+    KiSwapThread(Thread, KeGetCurrentPrcb());
+}