- Invert CONFIG_SMP defines as requested by Hartmut
[reactos.git] / reactos / ntoskrnl / ke / kthread.c
index 366e39b..57c775c 100644 (file)
@@ -3,7 +3,7 @@
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/kthread.c
  * PURPOSE:         Microkernel thread support
- * 
+ *
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  *                  David Welch (welch@cwcom.net)
  */
@@ -14,6 +14,8 @@
 #define NDEBUG
 #include <internal/debug.h>
 
+/* FIXME: NDK */
+#define MAXIMUM_SUSPEND_COUNT 0x7F
 #define THREAD_ALERT_INCREMENT 2
 
 extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
@@ -24,12 +26,11 @@ extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
 LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
 static ULONG PriorityListMask = 0;
 ULONG IdleProcessorMask = 0;
-extern BOOLEAN DoneInitYet;
 extern PETHREAD PspReaperList;
 
 /* FUNCTIONS *****************************************************************/
 
-STATIC 
+STATIC
 VOID
 KiRequestReschedule(CCHAR Processor)
 {
@@ -37,79 +38,72 @@ KiRequestReschedule(CCHAR Processor)
 
     Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
     Pcr->Prcb->QuantumEnd = TRUE;
-    KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
+    KiIpiSendRequest(1 << Processor, IPI_DPC);
 }
 
-STATIC 
+STATIC
 VOID
-KiInsertIntoThreadList(KPRIORITY Priority, 
+KiInsertIntoThreadList(KPRIORITY Priority,
                        PKTHREAD Thread)
 {
     ASSERT(Ready == Thread->State);
     ASSERT(Thread->Priority == Priority);
-    
+
     if (Priority >= MAXIMUM_PRIORITY || Priority < LOW_PRIORITY) {
-        
+
         DPRINT1("Invalid thread priority (%d)\n", Priority);
         KEBUGCHECK(0);
     }
-    
-    InsertTailList(&PriorityListHead[Priority], &Thread->QueueListEntry);
+
+    InsertTailList(&PriorityListHead[Priority], &Thread->WaitListEntry);
     PriorityListMask |= (1 << Priority);
 }
 
 STATIC
-VOID 
+VOID
 KiRemoveFromThreadList(PKTHREAD Thread)
 {
     ASSERT(Ready == Thread->State);
-    RemoveEntryList(&Thread->QueueListEntry);
+    RemoveEntryList(&Thread->WaitListEntry);
     if (IsListEmpty(&PriorityListHead[(ULONG)Thread->Priority])) {
-        
+
         PriorityListMask &= ~(1 << Thread->Priority);
     }
 }
 
 STATIC
-PKTHREAD 
-KiScanThreadList(KPRIORITY Priority, 
+PKTHREAD
+KiScanThreadList(KPRIORITY Priority,
                  KAFFINITY Affinity)
 {
-    PLIST_ENTRY current_entry;
     PKTHREAD current;
     ULONG Mask;
 
     Mask = (1 << Priority);
-    
+
     if (PriorityListMask & Mask) {
-        
-        current_entry = PriorityListHead[Priority].Flink;
-        
-        while (current_entry != &PriorityListHead[Priority]) {
-           
-            current = CONTAINING_RECORD(current_entry, KTHREAD, QueueListEntry);
-            
+
+        LIST_FOR_EACH(current, &PriorityListHead[Priority], KTHREAD, WaitListEntry) {
+
             if (current->State != Ready) {
-                
+
                 DPRINT1("%d/%d\n", &current, current->State);
             }
-            
+
             ASSERT(current->State == Ready);
-            
+
             if (current->Affinity & Affinity) {
-                
+
                 KiRemoveFromThreadList(current);
                 return(current);
             }
-            
-            current_entry = current_entry->Flink;
         }
     }
-    
+
     return(NULL);
 }
 
-VOID 
+VOID
 STDCALL
 KiDispatchThreadNoLock(ULONG NewThreadStatus)
 {
@@ -122,28 +116,28 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
             CurrentThread, NewThreadStatus, CurrentThread->State);
 
     CurrentThread->State = (UCHAR)NewThreadStatus;
-    
+
     if (NewThreadStatus == Ready) {
-            
+
         KiInsertIntoThreadList(CurrentThread->Priority,
                                CurrentThread);
     }
 
     Affinity = 1 << KeGetCurrentProcessorNumber();
-    
+
     for (CurrentPriority = HIGH_PRIORITY; CurrentPriority >= LOW_PRIORITY; CurrentPriority--) {
-        
+
         Candidate = KiScanThreadList(CurrentPriority, Affinity);
-        
+
         if (Candidate == CurrentThread) {
 
             Candidate->State = Running;
-            KeReleaseDispatcherDatabaseLockFromDpcLevel();     
+            KeReleaseDispatcherDatabaseLockFromDpcLevel();
             return;
         }
-        
+
         if (Candidate != NULL) {
-            
+
             PKTHREAD OldThread;
             PKTHREAD IdleThread;
 
@@ -156,80 +150,56 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
             IdleThread = KeGetCurrentPrcb()->IdleThread;
 
             if (OldThread == IdleThread) {
-                
+
                 IdleProcessorMask &= ~Affinity;
-                
+
             } else if (CurrentThread == IdleThread) {
-                
+
                 IdleProcessorMask |= Affinity;
             }
 
             MmUpdatePageDir(PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS));
 
             /* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */
-            KiArchContextSwitch(CurrentThread, OldThread);
+            DPRINT("You are : %x, swapping to: %x\n", OldThread, CurrentThread);
+            KiArchContextSwitch(CurrentThread);
+            DPRINT("You are : %x, swapped from: %x\n", OldThread, CurrentThread);
             return;
         }
     }
-    
+
     DPRINT1("CRITICAL: No threads are ready (CPU%d)\n", KeGetCurrentProcessorNumber());
     KEBUGCHECK(0);
 }
 
-VOID
-STDCALL
-KiBlockThread(PNTSTATUS Status, 
-              UCHAR Alertable, 
-              ULONG WaitMode,
-              UCHAR WaitReason)
+NTSTATUS
+NTAPI
+KiSwapThread(VOID)
 {
-    PKTHREAD Thread = KeGetCurrentThread();
-    PKWAIT_BLOCK WaitBlock;
+    PKTHREAD CurrentThread = KeGetCurrentThread();
 
-    if (Thread->ApcState.KernelApcPending) {
-    
-        DPRINT("Dispatching Thread as ready (APC!)\n");
-        
-        /* Remove Waits */
-        WaitBlock = Thread->WaitBlockList;
-        do {
-            RemoveEntryList (&WaitBlock->WaitListEntry);
-            WaitBlock = WaitBlock->NextWaitBlock;
-        } while (WaitBlock != Thread->WaitBlockList);
-        Thread->WaitBlockList = NULL;
-        
-        /* Dispatch it and return status */
-        KiDispatchThreadNoLock (Ready);
-        if (Status != NULL) *Status = STATUS_KERNEL_APC;
+    /* Find a new thread to run */
+    DPRINT("Dispatching Thread as blocked\n");
+    KiDispatchThreadNoLock(Waiting);
 
-    } else {
+    /* Lower IRQL back */
+    DPRINT("Lowering IRQL \n");
+    KfLowerIrql(CurrentThread->WaitIrql);
 
-        /* Set the Thread Data as Requested */
-        DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus);
-        Thread->Alertable = Alertable;
-        Thread->WaitMode = (UCHAR)WaitMode;
-        Thread->WaitReason = WaitReason;
-        
-        /* Dispatch it and return status */
-        KiDispatchThreadNoLock(Waiting);
-        DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus);
-        if (Status != NULL) *Status = Thread->WaitStatus;
-    }
-    
-    DPRINT("Releasing Dispatcher Lock\n");
-    KfLowerIrql(Thread->WaitIrql);
+    /* Return the wait status */
+    return CurrentThread->WaitStatus;
 }
 
-VOID 
+VOID
 STDCALL
 KiDispatchThread(ULONG NewThreadStatus)
 {
     KIRQL OldIrql;
 
-    if (!DoneInitYet || KeGetCurrentPrcb()->IdleThread == NULL) {
+    if (KeGetCurrentPrcb()->IdleThread == NULL) {
         return;
     }
-    
+
     OldIrql = KeAcquireDispatcherDatabaseLock();
     KiDispatchThreadNoLock(NewThreadStatus);
     KeLowerIrql(OldIrql);
@@ -237,70 +207,73 @@ KiDispatchThread(ULONG NewThreadStatus)
 
 VOID
 STDCALL
-KiUnblockThread(PKTHREAD Thread, 
-                PNTSTATUS WaitStatus, 
+KiUnblockThread(PKTHREAD Thread,
+                PNTSTATUS WaitStatus,
                 KPRIORITY Increment)
 {
     if (Terminated == Thread->State) {
 
         DPRINT("Can't unblock thread 0x%x because it's terminating\n",
                Thread);
-    
+
     } else if (Ready == Thread->State ||
                Running == Thread->State) {
-        
+
         DPRINT("Can't unblock thread 0x%x because it's %s\n",
                Thread, (Thread->State == Ready ? "ready" : "running"));
-    
+
     } else {
-        
-        ULONG Processor;
+
+        LONG Processor;
         KAFFINITY Affinity;
 
         /* FIXME: This propably isn't the right way to do it... */
         /* No it's not... i'll fix it later-- Alex */
         if (Thread->Priority < LOW_REALTIME_PRIORITY &&
             Thread->BasePriority < LOW_REALTIME_PRIORITY - 2) {
-          
+
             if (!Thread->PriorityDecrement && !Thread->DisableBoost) {
-                
+
                 Thread->Priority = Thread->BasePriority + Increment;
                 Thread->PriorityDecrement = Increment;
             }
-            
+
+            /* Also decrease quantum */
+            Thread->Quantum--;
+
         } else {
-            
-            Thread->Quantum = Thread->ApcState.Process->ThreadQuantum;
+
+            Thread->Quantum = Thread->QuantumReset;
         }
-     
+
         if (WaitStatus != NULL) {
-            
+
             Thread->WaitStatus = *WaitStatus;
         }
-        
+
         Thread->State = Ready;
         KiInsertIntoThreadList(Thread->Priority, Thread);
         Processor = KeGetCurrentProcessorNumber();
         Affinity = Thread->Affinity;
-        
+
         if (!(IdleProcessorMask & (1 << Processor) & Affinity) &&
              (IdleProcessorMask & ~(1 << Processor) & Affinity)) {
-            
-            ULONG i;
-            
+
+            LONG i;
+
             for (i = 0; i < KeNumberProcessors - 1; i++) {
-            
+
                 Processor++;
-                
+
                 if (Processor >= KeNumberProcessors) {
-                    
+
                     Processor = 0;
                 }
-                
+
                 if (IdleProcessorMask & (1 << Processor) & Affinity) {
-#if 0          
+#if 0
                     /* FIXME:
-                     *   Reschedule the threads on an other processor 
+                     *   Reschedule the threads on an other processor
                      */
                     KeReleaseDispatcherDatabaseLockFromDpcLevel();
                     KiRequestReschedule(Processor);
@@ -309,11 +282,58 @@ KiUnblockThread(PKTHREAD Thread,
                     break;
                 }
             }
-        } 
+        }
+    }
+}
+
+VOID
+STDCALL
+KiAdjustQuantumThread(IN PKTHREAD Thread)
+{
+    KPRIORITY Priority;
+
+    /* Don't adjust for RT threads */
+    if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
+        Thread->BasePriority < LOW_REALTIME_PRIORITY - 2)
+    {
+        /* Decrease Quantum by one and see if we've ran out */
+        if (--Thread->Quantum <= 0)
+        {
+            /* Return quantum */
+            Thread->Quantum = Thread->QuantumReset;
+
+            /* Calculate new Priority */
+            Priority = Thread->Priority - (Thread->PriorityDecrement + 1);
+
+            /* Normalize it if we've gone too low */
+            if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;
+
+            /* Reset the priority decrement, we've done it */
+            Thread->PriorityDecrement = 0;
+
+            /* Set the new priority, if needed */
+            if (Priority != Thread->Priority)
+            {
+                /* 
+                 * FIXME: This should be a call to KiSetPriorityThread but
+                 * due to the current ""scheduler"" in ROS, it can't be done
+                 * cleanly since it actualyl dispatches threads instead.
+                 */
+                Thread->Priority = Priority;
+            }
+            else
+            {
+                /* FIXME: Priority hasn't changed, find a new thread */
+            }
+        }
     }
+
+    /* Nothing to do... */
+    return;
 }
 
-VOID 
+
+VOID
 STDCALL
 KiSuspendThreadKernelRoutine(PKAPC Apc,
                              PKNORMAL_ROUTINE* NormalRoutine,
@@ -323,14 +343,14 @@ KiSuspendThreadKernelRoutine(PKAPC Apc,
 {
 }
 
-VOID 
+VOID
 STDCALL
 KiSuspendThreadNormalRoutine(PVOID NormalContext,
                              PVOID SystemArgument1,
                              PVOID SystemArgument2)
 {
     PKTHREAD CurrentThread = KeGetCurrentThread();
-    
+
     /* Non-alertable kernel-mode suspended wait */
     DPRINT("Waiting...\n");
     KeWaitForSingleObject(&CurrentThread->SuspendSemaphore,
@@ -347,8 +367,8 @@ KiSuspendThreadNormalRoutine(PVOID NormalContext,
 /*
  * @implemented
  */
-PKTHREAD 
-STDCALL 
+PKTHREAD
+STDCALL
 KeGetCurrentThread(VOID)
 {
 #ifdef CONFIG_SMP
@@ -374,51 +394,97 @@ KeSetPreviousMode(ULONG Mode)
 /*
  * @implemented
  */
-KPROCESSOR_MODE 
+KPROCESSOR_MODE
 STDCALL
 KeGetPreviousMode(VOID)
 {
     return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
 }
 
+BOOLEAN
+STDCALL
+KeDisableThreadApcQueueing(IN PKTHREAD Thread)
+{
+    KIRQL OldIrql;
+    BOOLEAN PreviousState;
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Save old state */
+    PreviousState = Thread->ApcQueueable;
+
+    /* Disable it now */
+    Thread->ApcQueueable = FALSE;
+
+    /* Release the Lock */
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+
+    /* Return old state */
+    return PreviousState;
+}
+
 VOID
 STDCALL
 KeRundownThread(VOID)
 {
     KIRQL OldIrql;
     PKTHREAD Thread = KeGetCurrentThread();
-    PLIST_ENTRY CurrentEntry;
+    PLIST_ENTRY NextEntry, ListHead;
     PKMUTANT Mutant;
-    
     DPRINT("KeRundownThread: %x\n", Thread);
 
+    /* Optimized path if nothing is on the list at the moment */
+    if (IsListEmpty(&Thread->MutantListHead)) return;
+
     /* Lock the Dispatcher Database */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
-    while (!IsListEmpty(&Thread->MutantListHead)) {
-    
+    /* Get the List Pointers */
+    ListHead = &Thread->MutantListHead;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
         /* Get the Mutant */
-       CurrentEntry = RemoveHeadList(&Thread->MutantListHead);
-        Mutant = CONTAINING_RECORD(CurrentEntry, KMUTANT, MutantListEntry);
-        ASSERT(Mutant->ApcDisable == 0);
-    
-        /* Uncondtionally abandon it */
+        Mutant = CONTAINING_RECORD(NextEntry, KMUTANT, MutantListEntry);
+        DPRINT1("Mutant: %p. Type, Size %x %x\n",
+                 Mutant,
+                 Mutant->Header.Type,
+                 Mutant->Header.Size);
+
+        /* 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 */
         DPRINT("Abandonning the Mutant\n");
         Mutant->Header.SignalState = 1;
         Mutant->Abandoned = TRUE;
         Mutant->OwnerThread = NULL;
-        RemoveEntryList(&Mutant->MutantListEntry);
-        
+
         /* Check if the Wait List isn't empty */
         DPRINT("Checking whether to wake the Mutant\n");
-        if (!IsListEmpty(&Mutant->Header.WaitListHead)) {
-            
+        if (!IsListEmpty(&Mutant->Header.WaitListHead))
+        {
             /* Wake the Mutant */
             DPRINT("Waking the Mutant\n");
             KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);
         }
+
+        /* Move on */
+        NextEntry = NextEntry->Flink;
     }
-   
+
     /* Release the Lock */
     KeReleaseDispatcherDatabaseLock(OldIrql);
 }
@@ -429,8 +495,9 @@ KeResumeThread(PKTHREAD Thread)
 {
     ULONG PreviousCount;
     KIRQL OldIrql;
-    
-    DPRINT("KeResumeThread (Thread %p called). %x, %x\n", Thread, Thread->SuspendCount, Thread->FreezeCount);
+
+    DPRINT("KeResumeThread (Thread %p called). %x, %x\n", Thread,
+            Thread->SuspendCount, Thread->FreezeCount);
 
     /* Lock the Dispatcher */
     OldIrql = KeAcquireDispatcherDatabaseLock();
@@ -440,25 +507,25 @@ KeResumeThread(PKTHREAD Thread)
 
     /* Check if it existed */
     if (PreviousCount) {
-        
+
         Thread->SuspendCount--;
-        
+
         /* Decrease the current Suspend Count and Check Freeze Count */
         if ((!Thread->SuspendCount) && (!Thread->FreezeCount)) {
-            
+
             /* Signal the Suspend Semaphore */
             Thread->SuspendSemaphore.Header.SignalState++;
             KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
         }
     }
-            
+
     /* Release Lock and return the Old State */
     KeReleaseDispatcherDatabaseLock(OldIrql);
     return PreviousCount;
 }
 
-BOOLEAN
-STDCALL
+VOID
+FASTCALL
 KiInsertQueueApc(PKAPC Apc,
                  KPRIORITY PriorityBoost);
 
@@ -471,41 +538,56 @@ STDCALL
 KeFreezeAllThreads(PKPROCESS Process)
 {
     KIRQL OldIrql;
-    PLIST_ENTRY CurrentEntry;
     PKTHREAD Current;
     PKTHREAD CurrentThread = KeGetCurrentThread();
 
     /* Acquire Lock */
     OldIrql = KeAcquireDispatcherDatabaseLock();
-    
+
+    /* If someone is already trying to free us, try again */
+    while (CurrentThread->FreezeCount)
+    {
+        /* Release and re-acquire the lock so the APC will go through */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        OldIrql = KeAcquireDispatcherDatabaseLock();
+    }
+
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
+
     /* Loop the Process's Threads */
-    CurrentEntry = Process->ThreadListHead.Flink;
-    while (CurrentEntry != &Process->ThreadListHead)
+    LIST_FOR_EACH(Current, &Process->ThreadListHead, KTHREAD, ThreadListEntry)
     {
-        /* Get the Thread */
-        Current = CONTAINING_RECORD(CurrentEntry, KTHREAD, ThreadListEntry);
-        
         /* Make sure it's not ours */
-        if (Current == CurrentThread) continue;
-        
-        /* Make sure it wasn't already frozen, and that it's not suspended */
-        if (!(++Current->FreezeCount) && !(Current->SuspendCount))
+        if (Current != CurrentThread)
         {
-            /* Insert the APC */
-            if (!KiInsertQueueApc(&Current->SuspendApc, IO_NO_INCREMENT)) 
+            /* Should be bother inserting the APC? */
+            if (Current->ApcQueueable)
             {
-                /* Unsignal the Semaphore, the APC already got inserted */
-                Current->SuspendSemaphore.Header.SignalState--;
+                /* Make sure it wasn't already frozen, and that it's not suspended */
+                if (!(++Current->FreezeCount) && !(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
+                    {
+                        /* Unsignal the Semaphore, the APC already got inserted */
+                        Current->SuspendSemaphore.Header.SignalState--;
+                    }
+                }
             }
         }
-
-        CurrentEntry = CurrentEntry->Flink;
     }
 
     /* Release the lock */
     KeReleaseDispatcherDatabaseLock(OldIrql);
 }
-    
+
 NTSTATUS
 STDCALL
 KeSuspendThread(PKTHREAD Thread)
@@ -514,27 +596,45 @@ KeSuspendThread(PKTHREAD Thread)
     KIRQL OldIrql;
 
     DPRINT("KeSuspendThread (Thread %p called). %x, %x\n", Thread, Thread->SuspendCount, Thread->FreezeCount);
-    
+
     /* Lock the Dispatcher */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
     /* Save the Old Count */
     PreviousCount = Thread->SuspendCount;
-    
-    /* Increment it */
-    Thread->SuspendCount++;
-    
-    /* Check if we should suspend it */
-    if (!PreviousCount && !Thread->FreezeCount) {
-    
-        /* Insert the APC */
-        if (!KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT)) {
-            
-            /* Unsignal the Semaphore, the APC already got inserted */
-            Thread->SuspendSemaphore.Header.SignalState--;
+
+    /* Handle the maximum */
+    if (PreviousCount == MAXIMUM_SUSPEND_COUNT)
+    {
+        /* Raise an exception */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        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
+            {
+                /* Unsignal the Semaphore, the APC already got inserted */
+                Thread->SuspendSemaphore.Header.SignalState--;
+            }
         }
     }
-    
+
     /* Release Lock and return the Old State */
     KeReleaseDispatcherDatabaseLock(OldIrql);
     return PreviousCount;
@@ -546,25 +646,25 @@ KeForceResumeThread(IN PKTHREAD Thread)
 {
     KIRQL OldIrql;
     ULONG PreviousCount;
-    
+
     /* Lock the Dispatcher Database and the APC Queue */
     OldIrql = KeAcquireDispatcherDatabaseLock();
-    
+
     /* Save the old Suspend Count */
-    PreviousCount = Thread->SuspendCount + Thread->FreezeCount;  
-    
+    PreviousCount = Thread->SuspendCount + Thread->FreezeCount;
+
     /* If the thread is suspended, wake it up!!! */
     if (PreviousCount) {
-            
+
         /* Unwait it completely */
         Thread->SuspendCount = 0;
         Thread->FreezeCount = 0;
-            
+
         /* Signal and satisfy */
         Thread->SuspendSemaphore.Header.SignalState++;
         KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
     }
-    
+
     /* Release Lock and return the Old State */
     KeReleaseDispatcherDatabaseLock(OldIrql);
     return PreviousCount;
@@ -578,36 +678,36 @@ KeAlertResumeThread(IN PKTHREAD Thread)
     KIRQL OldIrql;
 
     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-   
+
     /* Lock the Dispatcher Database and the APC Queue */
     OldIrql = KeAcquireDispatcherDatabaseLock();
     KiAcquireSpinLock(&Thread->ApcQueueLock);
 
     /* Return if Thread is already alerted. */
     if (Thread->Alerted[KernelMode] == FALSE) {
-       
+
         /* If it's Blocked, unblock if it we should */
         if (Thread->State == Waiting &&  Thread->Alertable) {
-            
+
             DPRINT("Aborting Wait\n");
             KiAbortWaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);
-       
+
         } else {
-           
+
             /* If not, simply Alert it */
             Thread->Alerted[KernelMode] = TRUE;
         }
     }
-    
+
     /* Save the old Suspend Count */
-    PreviousCount = Thread->SuspendCount;    
-    
+    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 */
         if (--Thread->SuspendCount) {
-            
+
             /* Signal and satisfy */
             Thread->SuspendSemaphore.Header.SignalState++;
             KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
@@ -622,7 +722,7 @@ KeAlertResumeThread(IN PKTHREAD Thread)
 
 BOOLEAN
 STDCALL
-KeAlertThread(PKTHREAD Thread, 
+KeAlertThread(PKTHREAD Thread,
               KPROCESSOR_MODE AlertMode)
 {
     KIRQL OldIrql;
@@ -630,31 +730,31 @@ KeAlertThread(PKTHREAD Thread,
 
     /* Acquire the Dispatcher Database Lock */
     OldIrql = KeAcquireDispatcherDatabaseLock();
-   
+
     /* Save the Previous State */
     PreviousState = Thread->Alerted[AlertMode];
-      
+
     /* Return if Thread is already alerted. */
     if (PreviousState == FALSE) {
-       
+
         /* If it's Blocked, unblock if it we should */
-        if (Thread->State == Waiting && 
+        if (Thread->State == Waiting &&
             (AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
             Thread->Alertable) {
-            
+
             DPRINT("Aborting Wait\n");
             KiAbortWaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);
-       
+
         } else {
-           
+
             /* If not, simply Alert it */
             Thread->Alerted[AlertMode] = TRUE;
         }
     }
-    
+
     /* Release the Dispatcher Lock */
     KeReleaseDispatcherDatabaseLock(OldIrql);
-    
+
     /* Return the old state */
     return PreviousState;
 }
@@ -680,195 +780,42 @@ KeCapturePersistentThreadState(IN PVOID CurrentThread,
  */
 VOID
 STDCALL
-KeInitializeThread(PKPROCESS Process, 
-                   PKTHREAD Thread, 
-                   BOOLEAN First)
+KeInitializeThread(PKPROCESS Process,
+                   PKTHREAD Thread,
+                   PKSYSTEM_ROUTINE SystemRoutine,
+                   PKSTART_ROUTINE StartRoutine,
+                   PVOID StartContext,
+                   PCONTEXT Context,
+                   PVOID Teb,
+                   PVOID KernelStack)
 {
-    PVOID KernelStack;
-    NTSTATUS Status;
-    extern unsigned int init_stack_top;
-    extern unsigned int init_stack;
-    PMEMORY_AREA StackArea;
-    ULONG i;
-    PHYSICAL_ADDRESS BoundaryAddressMultiple;
-  
-    /* Initialize the Boundary Address */
-    BoundaryAddressMultiple.QuadPart = 0;
-  
     /* Initalize the Dispatcher Header */
+    DPRINT("Initializing Dispatcher Header for New Thread: %x in Process: %x\n", Thread, Process);
     KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
                                  ThreadObject,
-                                 sizeof(KTHREAD),
+                                 sizeof(KTHREAD) / sizeof(LONG),
                                  FALSE);
-    InitializeListHead(&Thread->MutantListHead);
-    
-    /* If this is isn't the first thread, allocate the Kernel Stack */
-    if (!First) {
-        
-        PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
-        KernelStack = NULL;
-      
-        MmLockAddressSpace(MmGetKernelAddressSpace());
-        Status = MmCreateMemoryArea(NULL,
-                                    MmGetKernelAddressSpace(),
-                                    MEMORY_AREA_KERNEL_STACK,
-                                    &KernelStack,
-                                    MM_STACK_SIZE,
-                                    0,
-                                    &StackArea,
-                                    FALSE,
-                                    FALSE,
-                                    BoundaryAddressMultiple);
-        MmUnlockAddressSpace(MmGetKernelAddressSpace());
-      
-        /* Check for Success */
-        if (!NT_SUCCESS(Status)) {
-            
-            DPRINT1("Failed to create thread stack\n");
-            KEBUGCHECK(0);
-        }
-        
-        /* Mark the Stack */
-        for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) {
 
-            Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
-            
-            /* Check for success */
-            if (!NT_SUCCESS(Status)) {
-                
-                KEBUGCHECK(0);
-            }
-        }
-        
-        /* Create a Virtual Mapping for it */
-        Status = MmCreateVirtualMapping(NULL,
-                                        KernelStack,
-                                        PAGE_READWRITE,
-                                        Page,
-                                        MM_STACK_SIZE / PAGE_SIZE);
-        
-        /* Check for success */
-        if (!NT_SUCCESS(Status)) {
-            
-            KEBUGCHECK(0);
-        }
-        
-        /* Set the Kernel Stack */
-        Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
-        Thread->StackBase    = (PCHAR)KernelStack + MM_STACK_SIZE;
-        Thread->StackLimit   = (ULONG_PTR)KernelStack;
-        Thread->KernelStack  = (PCHAR)KernelStack + MM_STACK_SIZE;
-        
-    } else {
-        
-        /* Use the Initial Stack */
-        Thread->InitialStack = (PCHAR)init_stack_top;
-        Thread->StackBase = (PCHAR)init_stack_top;
-        Thread->StackLimit = (ULONG_PTR)init_stack;
-        Thread->KernelStack = (PCHAR)init_stack_top;
-    }
+    DPRINT("Thread Header Created. SystemRoutine: %x, StartRoutine: %x with Context: %x\n",
+            SystemRoutine, StartRoutine, StartContext);
+    DPRINT("UserMode Information. Context: %x, Teb: %x\n", Context, Teb);
 
-    /* 
-     * Establish the pde's for the new stack and the thread structure within the 
-     * address space of the new process. They are accessed while taskswitching or
-     * while handling page faults. At this point it isn't possible to call the 
-     * page fault handler for the missing pde's. 
-     */
-    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
-    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
+    /* Initialize the Mutant List */
+    InitializeListHead(&Thread->MutantListHead);
+
+    /* Setup the Service Descriptor Table for Native Calls */
+    Thread->ServiceTable = KeServiceDescriptorTable;
 
-    /* Set the Thread to initalized */
-    Thread->State = Initialized;
-    
-    /* The Native API function will initialize the TEB field later */
-    Thread->Teb = NULL;
-    
-    /* Initialize stuff to zero */
-    Thread->TlsArray = NULL;
-    Thread->DebugActive = 0;
-    Thread->Alerted[0] = 0;
-    Thread->Alerted[1] = 0;
-    Thread->Iopl = 0;
-    
-    /* Set up FPU/NPX Stuff */
-    Thread->NpxState = NPX_STATE_INVALID;
-    Thread->NpxIrql = 0;
-   
     /* Setup APC Fields */
     InitializeListHead(&Thread->ApcState.ApcListHead[0]);
     InitializeListHead(&Thread->ApcState.ApcListHead[1]);
     Thread->ApcState.Process = Process;
-    Thread->ApcState.KernelApcInProgress = 0;
-    Thread->ApcState.KernelApcPending = 0;
-    Thread->ApcState.UserApcPending = 0;
     Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
     Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
     Thread->ApcStateIndex = OriginalApcEnvironment;
-    Thread->ApcQueueable = TRUE;
-    RtlZeroMemory(&Thread->SavedApcState, sizeof(KAPC_STATE));
     KeInitializeSpinLock(&Thread->ApcQueueLock);
-    
-    /* Setup Wait Fields */
-    Thread->WaitStatus = STATUS_SUCCESS;
-    Thread->WaitIrql = PASSIVE_LEVEL;
-    Thread->WaitMode = 0;
-    Thread->WaitNext = FALSE;
-    Thread->WaitListEntry.Flink = NULL;
-    Thread->WaitListEntry.Blink = NULL;
-    Thread->WaitTime = 0;
-    Thread->WaitBlockList = NULL;
-    RtlZeroMemory(Thread->WaitBlock, sizeof(KWAIT_BLOCK) * 4);
-    RtlZeroMemory(&Thread->Timer, sizeof(KTIMER));
-    KeInitializeTimer(&Thread->Timer);
-    
-    /* Setup scheduler Fields */
-    Thread->BasePriority = Process->BasePriority;
-    Thread->DecrementCount = 0;
-    Thread->PriorityDecrement = 0;
-    Thread->Quantum = Process->ThreadQuantum;
-    Thread->Saturation = 0;
-    Thread->Priority = Process->BasePriority; 
-    Thread->UserAffinity = Process->Affinity;
-    Thread->SystemAffinityActive = 0;
-    Thread->Affinity = Process->Affinity;
-    Thread->Preempted = 0;
-    Thread->ProcessReadyQueue = 0;
-    Thread->KernelStackResident = 1;
-    Thread->NextProcessor = 0;
-    Thread->ContextSwitches = 0;
-    
-    /* Setup Queue Fields */
-    Thread->Queue = NULL;
-    Thread->QueueListEntry.Flink = NULL;
-    Thread->QueueListEntry.Blink = NULL;
-
-    /* Setup Misc Fields */
-    Thread->LegoData = 0; 
-    Thread->PowerState = 0;
-    Thread->ServiceTable = KeServiceDescriptorTable;
-    Thread->CallbackStack = NULL;
-    Thread->Win32Thread = NULL;
-    Thread->TrapFrame = NULL;
-    Thread->EnableStackSwap = 0;
-    Thread->LargeStack = 0;
-    Thread->ResourceIndex = 0;
-    Thread->PreviousMode = KernelMode;
-    Thread->KernelTime = 0;
-    Thread->UserTime = 0;
-    Thread->AutoAlignment = Process->AutoAlignment;
-   
-  /* FIXME OPTIMIZATION OF DOOM. DO NOT ENABLE FIXME */
-#if 0
-  Thread->WaitBlock[3].Object = (PVOID)&Thread->Timer;
-  Thread->WaitBlock[3].Thread = Thread;
-  Thread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
-  Thread->WaitBlock[3].WaitType = WaitAny;
-  Thread->WaitBlock[3].NextWaitBlock = NULL;
-  InsertTailList(&Thread->Timer.Header.WaitListHead,
-                 &Thread->WaitBlock[3].WaitListEntry);
-#endif
 
-    /* Initialize the Suspend APC */  
+    /* Initialize the Suspend APC */
     KeInitializeApc(&Thread->SuspendApc,
                     Thread,
                     OriginalApcEnvironment,
@@ -877,23 +824,75 @@ KeInitializeThread(PKPROCESS Process,
                     KiSuspendThreadNormalRoutine,
                     KernelMode,
                     NULL);
-     
+
     /* Initialize the Suspend Semaphore */
     KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
-    
-    /* Insert the Thread into the Process's Thread List */
-    InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
-  
-    /* Set up the Suspend Counts */
-    Thread->FreezeCount = 0;
-    Thread->SuspendCount = 0;
-    ((PETHREAD)Thread)->ReaperLink = NULL; /* Union. Will also clear termination port */
-   
-    /* Do x86 specific part */
-}
 
-/*
- * @implemented
+    /* FIXME OPTIMIZATION OF DOOM. DO NOT ENABLE FIXME */
+#if 0
+    Thread->WaitBlock[3].Object = (PVOID)&Thread->Timer;
+    Thread->WaitBlock[3].Thread = Thread;
+    Thread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
+    Thread->WaitBlock[3].WaitType = WaitAny;
+    Thread->WaitBlock[3].NextWaitBlock = NULL;
+    InsertTailList(&Thread->Timer.Header.WaitListHead,
+                   &Thread->WaitBlock[3].WaitListEntry);
+#endif
+    KeInitializeTimer(&Thread->Timer);
+
+    /* Set the TEB */
+    Thread->Teb = Teb;
+
+    /* Set the Thread Stacks */
+    Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
+    Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE;
+    Thread->StackLimit = (ULONG_PTR)KernelStack;
+    Thread->KernelStackResident = TRUE;
+
+    /*
+     * Establish the pde's for the new stack and the thread structure within the
+     * address space of the new process. They are accessed while taskswitching or
+     * while handling page faults. At this point it isn't possible to call the
+     * page fault handler for the missing pde's.
+     */
+    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
+    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
+
+    /* Initalize the Thread Context */
+    DPRINT("Initializing the Context for the thread: %x\n", Thread);
+    KiArchInitThreadWithContext(Thread,
+                                SystemRoutine,
+                                StartRoutine,
+                                StartContext,
+                                Context);
+
+    /* Setup scheduler Fields based on Parent */
+    DPRINT("Thread context created, setting Scheduler Data\n");
+    Thread->BasePriority = Process->BasePriority;
+    Thread->Quantum = Process->QuantumReset;
+    Thread->QuantumReset = Process->QuantumReset;
+    Thread->Affinity = Process->Affinity;
+    Thread->Priority = Process->BasePriority;
+    Thread->UserAffinity = Process->Affinity;
+    Thread->DisableBoost = Process->DisableBoost;
+    Thread->AutoAlignment = Process->AutoAlignment;
+    Thread->Iopl = Process->Iopl;
+
+    /* Set the Thread to initalized */
+    Thread->State = Initialized;
+
+    /*
+     * Insert the Thread into the Process's Thread List
+     * Note, this is the KTHREAD Thread List. It is removed in
+     * ke/kthread.c!KeTerminateThread.
+     */
+    InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
+    DPRINT("Thread initalized\n");
+}
+
+
+/*
+ * @implemented
  */
 KPRIORITY
 STDCALL
@@ -912,52 +911,11 @@ KeQueryRuntimeThread(IN PKTHREAD Thread,
 {
     /* Return the User Time */
     *UserTime = Thread->UserTime;
-    
+
     /* Return the Kernel Time */
     return Thread->KernelTime;
 }
 
-VOID
-KeFreeStackPage(PVOID Context, 
-                MEMORY_AREA* MemoryArea, 
-                PVOID Address, 
-                PFN_TYPE Page, 
-                SWAPENTRY SwapEntry, 
-                BOOLEAN Dirty)
-{
-    ASSERT(SwapEntry == 0);
-    if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
-}
-
-NTSTATUS
-KeReleaseThread(PKTHREAD Thread)
-/*
- * FUNCTION: Releases the resource allocated for a thread by
- * KeInitializeThread
- * NOTE: The thread had better not be running when this is called
- */
-{
-  extern unsigned int init_stack;
-
-  /* FIXME - lock the process */
-  RemoveEntryList(&Thread->ThreadListEntry);
-  
-  if (Thread->StackLimit != (ULONG_PTR)init_stack)
-    {       
-      MmLockAddressSpace(MmGetKernelAddressSpace());
-      MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
-                            (PVOID)Thread->StackLimit,
-                            KeFreeStackPage,
-                            NULL);
-      MmUnlockAddressSpace(MmGetKernelAddressSpace());
-    }
-  Thread->StackLimit = 0;
-  Thread->InitialStack = NULL;
-  Thread->StackBase = NULL;
-  Thread->KernelStack = NULL;
-  return(STATUS_SUCCESS);
-}
-
 /*
  * @implemented
  */
@@ -968,7 +926,7 @@ KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
     PKTHREAD Thread = KeGetCurrentThread();
     BOOLEAN PreviousState;
     KIRQL OldIrql;
+
      /* Lock the Dispatcher Database */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
@@ -980,7 +938,7 @@ KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
 
     /* No, Release Lock */
     KeReleaseDispatcherDatabaseLock(OldIrql);
-        
+
     /* Return Old State */
     return PreviousState;
 }
@@ -996,7 +954,7 @@ KeRevertToUserAffinityThread(VOID)
     KIRQL OldIrql;
 
     ASSERT(CurrentThread->SystemAffinityActive != FALSE);
-        
+
     /* Lock the Dispatcher Database */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
@@ -1005,15 +963,15 @@ KeRevertToUserAffinityThread(VOID)
 
     /* Disable System Affinity */
     CurrentThread->SystemAffinityActive = FALSE;
-    
+
     /* Check if we need to Dispatch a New thread */
     if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) {
-        
+
         /* No, just release */
         KeReleaseDispatcherDatabaseLock(OldIrql);
-    
+
     } else {
-        
+
         /* We need to dispatch a new thread */
         CurrentThread->WaitIrql = OldIrql;
         KiDispatchThreadNoLock(Ready);
@@ -1031,7 +989,7 @@ KeSetIdealProcessorThread(IN PKTHREAD Thread,
 {
     CCHAR PreviousIdealProcessor;
     KIRQL OldIrql;
-    
+
     /* Lock the Dispatcher Database */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
@@ -1040,10 +998,10 @@ KeSetIdealProcessorThread(IN PKTHREAD Thread,
 
     /* Set New Ideal Processor */
     Thread->IdealProcessor = Processor;
-    
+
     /* Release Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);   
-    
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+
     /* Return Old Ideal Processor */
     return PreviousIdealProcessor;
 }
@@ -1059,7 +1017,7 @@ KeSetSystemAffinityThread(IN KAFFINITY Affinity)
     KIRQL OldIrql;
 
     ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
-        
+
     /* Lock the Dispatcher Database */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
@@ -1068,15 +1026,15 @@ KeSetSystemAffinityThread(IN KAFFINITY Affinity)
 
     /* Enable System Affinity */
     CurrentThread->SystemAffinityActive = TRUE;
-    
+
     /* Check if we need to Dispatch a New thread */
     if (Affinity & (1 << KeGetCurrentProcessorNumber())) {
-        
+
         /* No, just release */
         KeReleaseDispatcherDatabaseLock(OldIrql);
-    
+
     } else {
-        
+
         /* We need to dispatch a new thread */
         CurrentThread->WaitIrql = OldIrql;
         KiDispatchThreadNoLock(Ready);
@@ -1084,121 +1042,254 @@ KeSetSystemAffinityThread(IN KAFFINITY Affinity)
     }
 }
 
-/*
- * @implemented
- */
-LONG STDCALL
-KeSetBasePriorityThread (PKTHREAD      Thread,
-                        LONG           Increment)
-/*
- * Sets thread's base priority relative to the process' base priority
- * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
- */
+LONG
+STDCALL
+KeQueryBasePriorityThread(IN PKTHREAD Thread)
 {
-   KPRIORITY Priority;
-   if (Increment < -2)
-     {
-       Increment = -2;
-     }
-   else if (Increment > 2)
-     {
-       Increment = 2;
-     }
-   Priority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
-   if (Priority < LOW_PRIORITY)
-   {
-     Priority = LOW_PRIORITY;
-   }
-   else if (Priority >= MAXIMUM_PRIORITY)
-     {
-       Thread->BasePriority = HIGH_PRIORITY;
-     }
-   KeSetPriorityThread(Thread, Priority);
-   return 1;
+    LONG BasePriorityIncrement;
+    KIRQL OldIrql;
+    PKPROCESS Process;
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Get the Process */
+    Process = Thread->ApcStatePointer[0]->Process;
+
+    /* Calculate the BPI */
+    BasePriorityIncrement = Thread->BasePriority - Process->BasePriority;
+
+    /* If saturation occured, return the SI instead */
+    if (Thread->Saturation) BasePriorityIncrement = (HIGH_PRIORITY + 1) / 2 *
+                                                    Thread->Saturation;
+
+    /* Release Lock */
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+
+    /* Return Increment */
+    return BasePriorityIncrement;
 }
 
-/*
- * @implemented
- */
-KPRIORITY 
+VOID
 STDCALL
-KeSetPriorityThread(PKTHREAD Thread, 
-                    KPRIORITY Priority)
+KiSetPriorityThread(PKTHREAD Thread,
+                    KPRIORITY Priority,
+                    PBOOLEAN Released)
 {
-    KPRIORITY OldPriority;
-    KIRQL OldIrql;
-    PKTHREAD CurrentThread;
+    KPRIORITY OldPriority = Thread->Priority;
     ULONG Mask;
     int i;
     PKPCR Pcr;
+    DPRINT("Changing prio to : %lx\n", Priority);
 
-    if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY) {
-        
-        KEBUGCHECK(0);
-    }
-
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-
-    OldPriority = Thread->Priority;
+    /* Check if priority changed */
+    if (OldPriority != Priority)
+    {
+        /* Set it */
+        Thread->Priority = Priority;
 
-    if (OldPriority != Priority) {
-        
-        CurrentThread = KeGetCurrentThread();
-        
-        if (Thread->State == Ready) {
-            
+        /* Choose action based on thread's state */
+        if (Thread->State == Ready)
+        {
+            /* Remove it from the current queue */
             KiRemoveFromThreadList(Thread);
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-            KiInsertIntoThreadList(Priority, Thread);
             
-            if (CurrentThread->Priority < Priority) {
-                
+            /* Re-insert it at its current priority */
+            KiInsertIntoThreadList(Priority, Thread);
+
+            /* Check if the old priority was lower */
+            if (KeGetCurrentThread()->Priority < Priority)
+            {
+                /* Dispatch it immediately */
                 KiDispatchThreadNoLock(Ready);
-                KeLowerIrql(OldIrql);
-                return (OldPriority);
+                *Released = TRUE;
+                return;
             }
-        
-        } else if (Thread->State == Running)  {
-            
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-            
-            if (Priority < OldPriority) {
-                
+        }
+        else if (Thread->State == Running)
+        {
+            /* Check if the new priority is lower */
+            if (Priority < OldPriority)
+            {
                 /* Check for threads with a higher priority */
                 Mask = ~((1 << (Priority + 1)) - 1);
-                if (PriorityListMask & Mask) {
-                    
-                    if (Thread == CurrentThread) {
-                        
+                if (PriorityListMask & Mask)
+                {
+                    /* Found a thread, is it us? */
+                    if (Thread == KeGetCurrentThread())
+                    {
+                        /* Dispatch us */
                         KiDispatchThreadNoLock(Ready);
-                        KeLowerIrql(OldIrql);
-                        return (OldPriority);
-                        
-                    } else {
-                        
-                        for (i = 0; i < KeNumberProcessors; i++) {
-                            
+                        *Released = TRUE;
+                        return;
+                    } 
+                    else
+                    {
+                        /* Loop every CPU */
+                        for (i = 0; i < KeNumberProcessors; i++)
+                        {
+                            /* Get the PCR for this CPU */
                             Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-                            
-                            if (Pcr->Prcb->CurrentThread == Thread) {
 
+                            /* Reschedule if the new one is already on a CPU */
+                            if (Pcr->Prcb->CurrentThread == Thread)
+                            {
                                 KeReleaseDispatcherDatabaseLockFromDpcLevel();
                                 KiRequestReschedule(i);
-                                KeLowerIrql(OldIrql);
-                                return (OldPriority);
+                                *Released = TRUE;
+                                return;
                             }
                         }
                     }
                 }
             }
-        }  else  {
-            
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
         }
     }
-    
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return(OldPriority);
+
+    /* Return to caller */
+    return;
+}
+
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+KeSetBasePriorityThread(PKTHREAD Thread,
+                        LONG Increment)
+{
+    KIRQL OldIrql;
+    PKPROCESS Process;
+    KPRIORITY Priority;
+    KPRIORITY CurrentBasePriority;
+    KPRIORITY BasePriority;
+    BOOLEAN Released = FALSE;
+    LONG CurrentIncrement;
+       
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Get the process and calculate current BP and BPI */
+    Process = Thread->ApcStatePointer[0]->Process;
+    CurrentBasePriority = Thread->BasePriority;
+    CurrentIncrement = CurrentBasePriority - Process->BasePriority;
+
+    /* Change to use the SI if Saturation was used */
+    if (Thread->Saturation) CurrentIncrement = (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)
+            BasePriority = LOW_REALTIME_PRIORITY;
+
+        /* Check if it's too high */
+        if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;
+
+        /* We are at RTP, so use the raw BP */
+        Priority = BasePriority;
+    }
+    else
+    {
+        /* Check if it's entering RTP */
+        if (BasePriority >= LOW_REALTIME_PRIORITY)
+            BasePriority = LOW_REALTIME_PRIORITY - 1;
+
+        /* Check if it's too low */
+        if (BasePriority <= LOW_PRIORITY)
+            BasePriority = 1;
+
+        /* If Saturation is used, then use the raw BP */
+        if (Thread->Saturation)
+        {
+            Priority = BasePriority;
+        }
+        else
+        {
+            /* Calculate the new priority */
+            Priority = Thread->Priority + (BasePriority - CurrentBasePriority)-
+                       Thread->PriorityDecrement;
+
+            /* Make sure it won't enter RTP ranges */
+            if (Priority >= LOW_REALTIME_PRIORITY)
+                Priority = LOW_REALTIME_PRIORITY - 1;
+        }
+    }
+
+    /* Finally set the new base priority */
+    Thread->BasePriority = BasePriority;
+
+    /* Reset the decrements */
+    Thread->PriorityDecrement = 0;
+
+    /* If the priority will change, reset quantum and change it for real */
+    if (Priority != Thread->Priority)
+    {
+        Thread->Quantum = Thread->QuantumReset;
+        KiSetPriorityThread(Thread, Priority, &Released);
+    }
+
+    /* Release Lock if needed */
+    if (!Released)
+    {
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+    else
+    {
+        KeLowerIrql(OldIrql);
+    }
+
+    /* Return the Old Increment */
+    return CurrentIncrement;
+}
+
+/*
+ * @implemented
+ */
+KPRIORITY
+STDCALL
+KeSetPriorityThread(PKTHREAD Thread,
+                    KPRIORITY Priority)
+{
+    KPRIORITY OldPriority;
+    BOOLEAN Released = FALSE;
+    KIRQL OldIrql;
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Save the old Priority */
+    OldPriority = Thread->Priority;
+
+    /* Reset the Quantum and Decrements */
+    Thread->Quantum = Thread->QuantumReset;
+    Thread->PriorityDecrement = 0;
+
+    /* Set the new Priority */
+    KiSetPriorityThread(Thread, Priority, &Released);
+
+    /* Release Lock if needed */
+    if (!Released)
+    {
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+    else
+    {
+        KeLowerIrql(OldIrql);
+    }
+
+    /* Return Old Priority */
+    return OldPriority;
 }
 
 /*
@@ -1206,55 +1297,60 @@ KeSetPriorityThread(PKTHREAD Thread,
  *
  * Sets thread's affinity
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 KeSetAffinityThread(PKTHREAD Thread,
                     KAFFINITY Affinity)
 {
     KIRQL OldIrql;
-    ULONG i;
+    LONG i;
     PKPCR Pcr;
     KAFFINITY ProcessorMask;
 
     DPRINT("KeSetAffinityThread(Thread %x, Affinity %x)\n", Thread, Affinity);
 
-    ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
+    /* Verify correct affinity */
+    if ((Affinity & Thread->ApcStatePointer[0]->Process->Affinity) !=
+        Affinity || !Affinity)
+    {
+        KEBUGCHECK(INVALID_AFFINITY_SET);
+    }
 
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
     Thread->UserAffinity = Affinity;
-    
+
     if (Thread->SystemAffinityActive == FALSE) {
-        
+
         Thread->Affinity = Affinity;
-        
+
         if (Thread->State == Running) {
-            
-            ProcessorMask = 1 << KeGetCurrentKPCR()->ProcessorNumber;
+
+            ProcessorMask = 1 << KeGetCurrentProcessorNumber();
             if (Thread == KeGetCurrentThread()) {
-                
+
                 if (!(Affinity & ProcessorMask)) {
-                    
+
                     KiDispatchThreadNoLock(Ready);
                     KeLowerIrql(OldIrql);
                     return STATUS_SUCCESS;
                 }
-                
+
             } else {
-                
+
                 for (i = 0; i < KeNumberProcessors; i++) {
-                    
+
                     Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
                     if (Pcr->Prcb->CurrentThread == Thread) {
-                        
+
                         if (!(Affinity & ProcessorMask)) {
-                            
+
                             KeReleaseDispatcherDatabaseLockFromDpcLevel();
                             KiRequestReschedule(i);
                             KeLowerIrql(OldIrql);
                             return STATUS_SUCCESS;
                         }
-                        
+
                         break;
                     }
                 }
@@ -1263,7 +1359,7 @@ KeSetAffinityThread(PKTHREAD Thread,
             }
         }
     }
-    
+
     KeReleaseDispatcherDatabaseLock(OldIrql);
     return STATUS_SUCCESS;
 }
@@ -1278,20 +1374,23 @@ KeTerminateThread(IN KPRIORITY Increment)
 {
     KIRQL OldIrql;
     PKTHREAD Thread = KeGetCurrentThread();
-    
+
     /* Lock the Dispatcher Database and the APC Queue */
     DPRINT("Terminating\n");
     OldIrql = KeAcquireDispatcherDatabaseLock();
-    
+
+    /* Remove the thread from the list */
+    RemoveEntryList(&Thread->ThreadListEntry);
+
     /* Insert into the Reaper List */
     DPRINT("List: %p\n", PspReaperList);
     ((PETHREAD)Thread)->ReaperLink = PspReaperList;
     PspReaperList = (PETHREAD)Thread;
     DPRINT("List: %p\n", PspReaperList);
-    
+
     /* Check if it's active */
     if (PspReaping == FALSE) {
-        
+
         /* Activate it. We use the internal function for speed, and use the Hyper Critical Queue */
         PspReaping = TRUE;
         DPRINT("Terminating\n");
@@ -1299,23 +1398,23 @@ KeTerminateThread(IN KPRIORITY Increment)
                       &PspReaperWorkItem.List,
                       FALSE);
     }
-    
+
     /* Handle Kernel Queues */
     if (Thread->Queue) {
-                 
+
         DPRINT("Waking Queue\n");
         RemoveEntryList(&Thread->QueueListEntry);
         KiWakeQueue(Thread->Queue);
     }
-    
+
     /* Signal the thread */
     Thread->DispatcherHeader.SignalState = TRUE;
     if (IsListEmpty(&Thread->DispatcherHeader.WaitListHead) != TRUE) {
-        
+
         /* Satisfy waits */
         KiWaitTest((PVOID)Thread, Increment);
     }
-    
+
     /* Find a new Thread */
     KiDispatchThreadNoLock(Terminated);
 }
@@ -1331,27 +1430,27 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
     KIRQL OldIrql;
     PKTHREAD Thread = KeGetCurrentThread();
     BOOLEAN OldState;
-   
+
     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-   
+
     /* Lock the Dispatcher Database and the APC Queue */
     OldIrql = KeAcquireDispatcherDatabaseLock();
     KiAcquireSpinLock(&Thread->ApcQueueLock);
-   
+
     /* Save the old State */
     OldState = Thread->Alerted[AlertMode];
-   
+
     /* If the Thread is Alerted, Clear it */
     if (OldState) {
-            
+
         Thread->Alerted[AlertMode] = FALSE;
-        
-    } else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
-        
+
+    } 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 */
     KiReleaseSpinLock(&Thread->ApcQueueLock);
     KeReleaseDispatcherDatabaseLock(OldIrql);
@@ -1362,21 +1461,21 @@ VOID
 KiServiceCheck (VOID)
 {
     PKTHREAD Thread = KeGetCurrentThread();
-    
+
     /* Check if we need to inialize Win32 for this Thread */
     if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
-    
-        /* We do. Initialize it and save the new table */  
-        PsInitWin32Thread((PETHREAD)Thread);
+
+        /* We do. Initialize it and save the new table */
         Thread->ServiceTable = KeServiceDescriptorTableShadow;
+        PsInitWin32Thread((PETHREAD)Thread);
     }
 }
 
-/* 
+/*
  *
  * NOT EXPORTED
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtAlertResumeThread(IN  HANDLE ThreadHandle,
                     OUT PULONG SuspendCount)
@@ -1388,20 +1487,18 @@ NtAlertResumeThread(IN  HANDLE ThreadHandle,
 
     /* Check if parameters are valid */
     if(PreviousMode != KernelMode) {
-     
+
         _SEH_TRY {
-            
-            ProbeForWrite(SuspendCount,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-       
+
+            ProbeForWriteUlong(SuspendCount);
+
         } _SEH_HANDLE {
-            
+
             Status = _SEH_GetExceptionCode();
-            
+
         } _SEH_END;
     }
-   
+
     /* Reference the Object */
     Status = ObReferenceObjectByHandle(ThreadHandle,
                                        THREAD_SUSPEND_RESUME,
@@ -1409,40 +1506,40 @@ NtAlertResumeThread(IN  HANDLE ThreadHandle,
                                        PreviousMode,
                                        (PVOID*)&Thread,
                                        NULL);
-   
-    /* Check for Success */ 
+
+    /* Check for Success */
     if (NT_SUCCESS(Status)) {
-   
+
         /* Call the Kernel Function */
         PreviousState = KeAlertResumeThread(&Thread->Tcb);
-   
+
         /* Dereference Object */
         ObDereferenceObject(Thread);
-        
+
         if (SuspendCount) {
-        
+
             _SEH_TRY {
-        
+
                 *SuspendCount = PreviousState;
-            
+
             } _SEH_HANDLE {
-            
+
                 Status = _SEH_GetExceptionCode();
-            
+
             } _SEH_END;
         }
     }
-    
+
     /* Return status */
     return Status;
 }
 
-/* 
+/*
  * @implemented
  *
  * EXPORTED
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtAlertThread (IN HANDLE ThreadHandle)
 {
@@ -1457,27 +1554,27 @@ NtAlertThread (IN HANDLE ThreadHandle)
                                        PreviousMode,
                                        (PVOID*)&Thread,
                                        NULL);
-   
-    /* Check for Success */ 
+
+    /* Check for Success */
     if (NT_SUCCESS(Status)) {
-   
-        /* 
+
+        /*
          * Do an alert depending on the processor mode. If some kmode code wants to
          * enforce a umode alert it should call KeAlertThread() directly. If kmode
          * code wants to do a kmode alert it's sufficient to call it with Zw or just
-         * use KeAlertThread() directly 
+         * use KeAlertThread() directly
          */
         KeAlertThread(&Thread->Tcb, PreviousMode);
-   
+
         /* Dereference Object */
         ObDereferenceObject(Thread);
     }
-    
+
     /* Return status */
     return Status;
 }
 
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtDelayExecution(IN BOOLEAN Alertable,
                  IN PLARGE_INTEGER DelayInterval)
@@ -1485,31 +1582,35 @@ NtDelayExecution(IN BOOLEAN Alertable,
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     LARGE_INTEGER SafeInterval;
     NTSTATUS Status;
-   
+
     /* Check if parameters are valid */
     if(PreviousMode != KernelMode) {
-     
+
+        Status = STATUS_SUCCESS;
+        
         _SEH_TRY {
-            
-            ProbeForRead(DelayInterval,
-                         sizeof(LARGE_INTEGER),
-                         sizeof(ULONG));
-            
+
             /* make a copy on the kernel stack and let DelayInterval point to it so
                we don't need to wrap KeDelayExecutionThread in SEH! */
-            SafeInterval = *DelayInterval;
-       
+            SafeInterval = ProbeForReadLargeInteger(DelayInterval);
+            DelayInterval = &SafeInterval;
+
         } _SEH_HANDLE {
-            
+
             Status = _SEH_GetExceptionCode();
         } _SEH_END;
+        
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
    }
 
    /* Call the Kernel Function */
    Status = KeDelayExecutionThread(PreviousMode,
                                    Alertable,
-                                   &SafeInterval);
-   
+                                   DelayInterval);
+
    /* Return Status */
    return Status;
 }