- Invert CONFIG_SMP defines as requested by Hartmut
[reactos.git] / reactos / ntoskrnl / ke / kthread.c
index 42db43b..57c775c 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
-#ifndef MUTANT_INCREMENT
-#define MUTANT_INCREMENT                1
-#endif
-
+/* FIXME: NDK */
+#define MAXIMUM_SUSPEND_COUNT 0x7F
 #define THREAD_ALERT_INCREMENT 2
 
 extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
@@ -28,7 +26,6 @@ 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 *****************************************************************/
@@ -41,7 +38,7 @@ 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
@@ -79,7 +76,6 @@ PKTHREAD
 KiScanThreadList(KPRIORITY Priority,
                  KAFFINITY Affinity)
 {
-    PLIST_ENTRY current_entry;
     PKTHREAD current;
     ULONG Mask;
 
@@ -87,11 +83,7 @@ KiScanThreadList(KPRIORITY Priority,
 
     if (PriorityListMask & Mask) {
 
-        current_entry = PriorityListHead[Priority].Flink;
-
-        while (current_entry != &PriorityListHead[Priority]) {
-
-            current = CONTAINING_RECORD(current_entry, KTHREAD, WaitListEntry);
+        LIST_FOR_EACH(current, &PriorityListHead[Priority], KTHREAD, WaitListEntry) {
 
             if (current->State != Ready) {
 
@@ -105,8 +97,6 @@ KiScanThreadList(KPRIORITY Priority,
                 KiRemoveFromThreadList(current);
                 return(current);
             }
-
-            current_entry = current_entry->Flink;
         }
     }
 
@@ -182,48 +172,22 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
     KEBUGCHECK(0);
 }
 
-VOID
-STDCALL
-KiBlockThread(PNTSTATUS Status,
-              UCHAR Alertable,
-              ULONG WaitMode,
-              UCHAR WaitReason)
+NTSTATUS
+NTAPI
+KiSwapThread(VOID)
 {
-    PKTHREAD Thread = KeGetCurrentThread();
-    PKWAIT_BLOCK WaitBlock;
-
-    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;
-
-    } else {
+    PKTHREAD CurrentThread = KeGetCurrentThread();
 
-        /* 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;
+    /* Find a new thread to run */
+    DPRINT("Dispatching Thread as blocked\n");
+    KiDispatchThreadNoLock(Waiting);
 
-        /* Dispatch it and return status */
-        KiDispatchThreadNoLock(Waiting);
-        DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus);
-        if (Status != NULL) *Status = Thread->WaitStatus;
-    }
+    /* Lower IRQL back */
+    DPRINT("Lowering IRQL \n");
+    KfLowerIrql(CurrentThread->WaitIrql);
 
-    DPRINT("Releasing Dispatcher Lock\n");
-    KfLowerIrql(Thread->WaitIrql);
+    /* Return the wait status */
+    return CurrentThread->WaitStatus;
 }
 
 VOID
@@ -232,7 +196,7 @@ KiDispatchThread(ULONG NewThreadStatus)
 {
     KIRQL OldIrql;
 
-    if (!DoneInitYet || KeGetCurrentPrcb()->IdleThread == NULL) {
+    if (KeGetCurrentPrcb()->IdleThread == NULL) {
         return;
     }
 
@@ -260,7 +224,7 @@ KiUnblockThread(PKTHREAD Thread,
 
     } else {
 
-        ULONG Processor;
+        LONG Processor;
         KAFFINITY Affinity;
 
         /* FIXME: This propably isn't the right way to do it... */
@@ -274,6 +238,9 @@ KiUnblockThread(PKTHREAD Thread,
                 Thread->PriorityDecrement = Increment;
             }
 
+            /* Also decrease quantum */
+            Thread->Quantum--;
+
         } else {
 
             Thread->Quantum = Thread->QuantumReset;
@@ -292,7 +259,7 @@ KiUnblockThread(PKTHREAD Thread,
         if (!(IdleProcessorMask & (1 << Processor) & Affinity) &&
              (IdleProcessorMask & ~(1 << Processor) & Affinity)) {
 
-            ULONG i;
+            LONG i;
 
             for (i = 0; i < KeNumberProcessors - 1; i++) {
 
@@ -319,6 +286,53 @@ KiUnblockThread(PKTHREAD Thread,
     }
 }
 
+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
 STDCALL
 KiSuspendThreadKernelRoutine(PKAPC Apc,
@@ -387,42 +401,88 @@ 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);
+        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);
+        }
 
-        /* Uncondtionally abandon it */
+        /* 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 */
@@ -436,7 +496,8 @@ 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();
@@ -463,8 +524,8 @@ KeResumeThread(PKTHREAD Thread)
     return PreviousCount;
 }
 
-BOOLEAN
-STDCALL
+VOID
+FASTCALL
 KiInsertQueueApc(PKAPC Apc,
                  KPRIORITY PriorityBoost);
 
@@ -477,35 +538,50 @@ STDCALL
 KeFreezeAllThreads(PKPROCESS Process)
 {
     KIRQL OldIrql;
-    PLIST_ENTRY CurrentEntry;
     PKTHREAD Current;
     PKTHREAD CurrentThread = KeGetCurrentThread();
 
     /* Acquire Lock */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
-    /* Loop the Process's Threads */
-    CurrentEntry = Process->ThreadListHead.Flink;
-    while (CurrentEntry != &Process->ThreadListHead)
+    /* If someone is already trying to free us, try again */
+    while (CurrentThread->FreezeCount)
     {
-        /* Get the Thread */
-        Current = CONTAINING_RECORD(CurrentEntry, KTHREAD, ThreadListEntry);
+        /* Release and re-acquire the lock so the APC will go through */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        OldIrql = KeAcquireDispatcherDatabaseLock();
+    }
 
-        /* Make sure it's not ours */
-        if (Current == CurrentThread) continue;
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
 
-        /* Make sure it wasn't already frozen, and that it's not suspended */
-        if (!(++Current->FreezeCount) && !(Current->SuspendCount))
+    /* Loop the Process's Threads */
+    LIST_FOR_EACH(Current, &Process->ThreadListHead, KTHREAD, ThreadListEntry)
+    {
+        /* Make sure it's not ours */
+        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 */
@@ -527,17 +603,35 @@ KeSuspendThread(PKTHREAD Thread)
     /* Save the Old Count */
     PreviousCount = Thread->SuspendCount;
 
-    /* Increment it */
-    Thread->SuspendCount++;
-
-    /* Check if we should suspend it */
-    if (!PreviousCount && !Thread->FreezeCount) {
+    /* Handle the maximum */
+    if (PreviousCount == MAXIMUM_SUSPEND_COUNT)
+    {
+        /* Raise an exception */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        RtlRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
+    }
 
-        /* Insert the APC */
-        if (!KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT)) {
+    /* Should we bother to queue at all? */
+    if (Thread->ApcQueueable)
+    {
+        /* Increment the suspend count */
+        Thread->SuspendCount++;
 
-            /* Unsignal the Semaphore, the APC already got inserted */
-            Thread->SuspendSemaphore.Header.SignalState--;
+        /* 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--;
+            }
         }
     }
 
@@ -699,7 +793,7 @@ KeInitializeThread(PKPROCESS Process,
     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);
 
     DPRINT("Thread Header Created. SystemRoutine: %x, StartRoutine: %x with Context: %x\n",
@@ -948,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) {
+    /* Check if priority changed */
+    if (OldPriority != Priority)
+    {
+        /* Set it */
+        Thread->Priority = Priority;
 
-        KEBUGCHECK(0);
+        /* Choose action based on thread's state */
+        if (Thread->State == Ready)
+        {
+            /* Remove it from the current queue */
+            KiRemoveFromThreadList(Thread);
+            
+            /* 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);
+                *Released = TRUE;
+                return;
+            }
+        }
+        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)
+                {
+                    /* Found a thread, is it us? */
+                    if (Thread == KeGetCurrentThread())
+                    {
+                        /* Dispatch us */
+                        KiDispatchThreadNoLock(Ready);
+                        *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);
+
+                            /* Reschedule if the new one is already on a CPU */
+                            if (Pcr->Prcb->CurrentThread == Thread)
+                            {
+                                KeReleaseDispatcherDatabaseLockFromDpcLevel();
+                                KiRequestReschedule(i);
+                                *Released = TRUE;
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
+    /* 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();
 
-    OldPriority = Thread->Priority;
+    /* Get the process and calculate current BP and BPI */
+    Process = Thread->ApcStatePointer[0]->Process;
+    CurrentBasePriority = Thread->BasePriority;
+    CurrentIncrement = CurrentBasePriority - Process->BasePriority;
 
-    if (OldPriority != Priority) {
+    /* Change to use the SI if Saturation was used */
+    if (Thread->Saturation) CurrentIncrement = (HIGH_PRIORITY + 1) / 2 *
+                                               Thread->Saturation;
 
-        CurrentThread = KeGetCurrentThread();
+    /* 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;
+    }
 
-        if (Thread->State == Ready) {
+    /* 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;
 
-            KiRemoveFromThreadList(Thread);
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-            KiInsertIntoThreadList(Priority, Thread);
+        /* Check if it's too high */
+        if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;
 
-            if (CurrentThread->Priority < 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;
 
-                KiDispatchThreadNoLock(Ready);
-                KeLowerIrql(OldIrql);
-                return (OldPriority);
-            }
+        /* Check if it's too low */
+        if (BasePriority <= LOW_PRIORITY)
+            BasePriority = 1;
 
-        } else if (Thread->State == Running)  {
+        /* 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;
 
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
+            /* Make sure it won't enter RTP ranges */
+            if (Priority >= LOW_REALTIME_PRIORITY)
+                Priority = LOW_REALTIME_PRIORITY - 1;
+        }
+    }
 
-            if (Priority < OldPriority) {
+    /* Finally set the new base priority */
+    Thread->BasePriority = BasePriority;
 
-                /* Check for threads with a higher priority */
-                Mask = ~((1 << (Priority + 1)) - 1);
-                if (PriorityListMask & Mask) {
+    /* Reset the decrements */
+    Thread->PriorityDecrement = 0;
 
-                    if (Thread == CurrentThread) {
+    /* If the priority will change, reset quantum and change it for real */
+    if (Priority != Thread->Priority)
+    {
+        Thread->Quantum = Thread->QuantumReset;
+        KiSetPriorityThread(Thread, Priority, &Released);
+    }
 
-                        KiDispatchThreadNoLock(Ready);
-                        KeLowerIrql(OldIrql);
-                        return (OldPriority);
+    /* Release Lock if needed */
+    if (!Released)
+    {
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+    else
+    {
+        KeLowerIrql(OldIrql);
+    }
+
+    /* Return the Old Increment */
+    return CurrentIncrement;
+}
 
-                    } else {
+/*
+ * @implemented
+ */
+KPRIORITY
+STDCALL
+KeSetPriorityThread(PKTHREAD Thread,
+                    KPRIORITY Priority)
+{
+    KPRIORITY OldPriority;
+    BOOLEAN Released = FALSE;
+    KIRQL OldIrql;
 
-                        for (i = 0; i < KeNumberProcessors; i++) {
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
 
-                            Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
+    /* Save the old Priority */
+    OldPriority = Thread->Priority;
 
-                            if (Pcr->Prcb->CurrentThread == Thread) {
+    /* Reset the Quantum and Decrements */
+    Thread->Quantum = Thread->QuantumReset;
+    Thread->PriorityDecrement = 0;
 
-                                KeReleaseDispatcherDatabaseLockFromDpcLevel();
-                                KiRequestReschedule(i);
-                                KeLowerIrql(OldIrql);
-                                return (OldPriority);
-                            }
-                        }
-                    }
-                }
-            }
-        }  else  {
+    /* Set the new Priority */
+    KiSetPriorityThread(Thread, Priority, &Released);
 
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-        }
+    /* Release Lock if needed */
+    if (!Released)
+    {
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+    else
+    {
+        KeLowerIrql(OldIrql);
     }
 
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return(OldPriority);
+    /* Return Old Priority */
+    return OldPriority;
 }
 
 /*
@@ -1076,13 +1303,18 @@ 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();
 
@@ -1094,7 +1326,7 @@ KeSetAffinityThread(PKTHREAD Thread,
 
         if (Thread->State == Running) {
 
-            ProcessorMask = 1 << KeGetCurrentKPCR()->Number;
+            ProcessorMask = 1 << KeGetCurrentProcessorNumber();
             if (Thread == KeGetCurrentThread()) {
 
                 if (!(Affinity & ProcessorMask)) {
@@ -1213,7 +1445,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
 
         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;
@@ -1234,8 +1466,8 @@ KiServiceCheck (VOID)
     if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
 
         /* We do. Initialize it and save the new table */
-        PsInitWin32Thread((PETHREAD)Thread);
         Thread->ServiceTable = KeServiceDescriptorTableShadow;
+        PsInitWin32Thread((PETHREAD)Thread);
     }
 }
 
@@ -1258,9 +1490,7 @@ NtAlertResumeThread(IN  HANDLE ThreadHandle,
 
         _SEH_TRY {
 
-            ProbeForWrite(SuspendCount,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
+            ProbeForWriteUlong(SuspendCount);
 
         } _SEH_HANDLE {
 
@@ -1356,26 +1586,30 @@ NtDelayExecution(IN BOOLEAN Alertable,
     /* 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;