#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];
LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
static ULONG PriorityListMask = 0;
ULONG IdleProcessorMask = 0;
-extern BOOLEAN DoneInitYet;
extern PETHREAD PspReaperList;
/* FUNCTIONS *****************************************************************/
Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
Pcr->Prcb->QuantumEnd = TRUE;
- KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
+ KiIpiSendRequest(1 << Processor, IPI_DPC);
}
STATIC
KiScanThreadList(KPRIORITY Priority,
KAFFINITY Affinity)
{
- PLIST_ENTRY current_entry;
PKTHREAD current;
ULONG Mask;
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) {
KiRemoveFromThreadList(current);
return(current);
}
-
- current_entry = current_entry->Flink;
}
}
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
{
KIRQL OldIrql;
- if (!DoneInitYet || KeGetCurrentPrcb()->IdleThread == NULL) {
+ if (KeGetCurrentPrcb()->IdleThread == NULL) {
return;
}
} else {
- ULONG Processor;
+ LONG Processor;
KAFFINITY Affinity;
/* FIXME: This propably isn't the right way to do it... */
Thread->PriorityDecrement = Increment;
}
+ /* Also decrease quantum */
+ Thread->Quantum--;
+
} else {
Thread->Quantum = Thread->QuantumReset;
if (!(IdleProcessorMask & (1 << Processor) & Affinity) &&
(IdleProcessorMask & ~(1 << Processor) & Affinity)) {
- ULONG i;
+ LONG i;
for (i = 0; i < KeNumberProcessors - 1; i++) {
}
}
+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,
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 */
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();
return PreviousCount;
}
-BOOLEAN
-STDCALL
+VOID
+FASTCALL
KiInsertQueueApc(PKAPC Apc,
KPRIORITY PriorityBoost);
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 */
/* 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--;
+ }
}
}
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",
}
}
-/*
- * @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;
}
/*
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();
if (Thread->State == Running) {
- ProcessorMask = 1 << KeGetCurrentKPCR()->Number;
+ ProcessorMask = 1 << KeGetCurrentProcessorNumber();
if (Thread == KeGetCurrentThread()) {
if (!(Affinity & ProcessorMask)) {
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;
if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
/* We do. Initialize it and save the new table */
- PsInitWin32Thread((PETHREAD)Thread);
Thread->ServiceTable = KeServiceDescriptorTableShadow;
+ PsInitWin32Thread((PETHREAD)Thread);
}
}
_SEH_TRY {
- ProbeForWrite(SuspendCount,
- sizeof(HANDLE),
- sizeof(ULONG));
+ ProbeForWriteUlong(SuspendCount);
} _SEH_HANDLE {
/* 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;