ReactOS  0.4.13-dev-249-gcba1a2f
wait.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for wait.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID FASTCALL KiWaitTest (IN PVOID ObjectPointer, IN KPRIORITY Increment)
 
VOID FASTCALL KiUnlinkThread (IN PKTHREAD Thread, IN LONG_PTR WaitStatus)
 
VOID FASTCALL KiUnwaitThread (IN PKTHREAD Thread, IN LONG_PTR WaitStatus, IN KPRIORITY Increment)
 
VOID FASTCALL KiAcquireFastMutex (IN PFAST_MUTEX FastMutex)
 
VOID FASTCALL KiAcquireGuardedMutex (IN OUT PKGUARDED_MUTEX GuardedMutex)
 
VOID FASTCALL KiExitDispatcher (IN KIRQL OldIrql)
 
BOOLEAN NTAPI KeIsWaitListEmpty (IN PVOID Object)
 
NTSTATUS NTAPI KeDelayExecutionThread (IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
 
NTSTATUS NTAPI KeWaitForSingleObject (IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
 
NTSTATUS NTAPI KeWaitForMultipleObjects (IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
 
NTSTATUS NTAPI NtDelayExecution (IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file wait.c.

Function Documentation

◆ KeDelayExecutionThread()

NTSTATUS NTAPI KeDelayExecutionThread ( IN KPROCESSOR_MODE  WaitMode,
IN BOOLEAN  Alertable,
IN PLARGE_INTEGER Interval  OPTIONAL 
)

Definition at line 283 of file wait.c.

286 {
287  PKTIMER Timer;
288  PKWAIT_BLOCK TimerBlock;
290  NTSTATUS WaitStatus;
291  BOOLEAN Swappable;
292  PLARGE_INTEGER OriginalDueTime;
293  LARGE_INTEGER DueTime, NewDueTime, InterruptTime;
294  ULONG Hand = 0;
295 
296  if (Thread->WaitNext)
298  else
300 
301  /* If this is a user-mode wait of 0 seconds, yield execution */
302  if (!(Interval->QuadPart) && (WaitMode != KernelMode))
303  {
304  /* Make sure the wait isn't alertable or interrupting an APC */
305  if (!(Alertable) && !(Thread->ApcState.UserApcPending))
306  {
307  /* Yield execution */
308  return NtYieldExecution();
309  }
310  }
311 
312  /* Setup the original time and timer/wait blocks */
313  OriginalDueTime = Interval;
314  Timer = &Thread->Timer;
315  TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
316 
317  /* Check if the lock is already held */
318  if (!Thread->WaitNext) goto WaitStart;
319 
320  /* Otherwise, we already have the lock, so initialize the wait */
321  Thread->WaitNext = FALSE;
323 
324  /* Start wait loop */
325  for (;;)
326  {
327  /* Disable pre-emption */
328  Thread->Preempted = FALSE;
329 
330  /* Check if a kernel APC is pending and we're below APC_LEVEL */
331  if ((Thread->ApcState.KernelApcPending) && !(Thread->SpecialApcDisable) &&
332  (Thread->WaitIrql < APC_LEVEL))
333  {
334  /* Unlock the dispatcher */
335  KiReleaseDispatcherLock(Thread->WaitIrql);
336  }
337  else
338  {
339  /* Check if we have to bail out due to an alerted state */
340  WaitStatus = KiCheckAlertability(Thread, Alertable, WaitMode);
341  if (WaitStatus != STATUS_WAIT_0) break;
342 
343  /* Check if the timer expired */
344  InterruptTime.QuadPart = KeQueryInterruptTime();
345  if ((ULONGLONG)InterruptTime.QuadPart >= Timer->DueTime.QuadPart)
346  {
347  /* It did, so we don't need to wait */
348  goto NoWait;
349  }
350 
351  /* It didn't, so activate it */
352  Timer->Header.Inserted = TRUE;
353 
354  /* Handle Kernel Queues */
355  if (Thread->Queue) KiActivateWaiterQueue(Thread->Queue);
356 
357  /* Setup the wait information */
358  Thread->State = Waiting;
359 
360  /* Add the thread to the wait list */
361  KiAddThreadToWaitList(Thread, Swappable);
362 
363  /* Insert the timer and swap the thread */
364  ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);
366  KxInsertTimer(Timer, Hand);
367  WaitStatus = (NTSTATUS)KiSwapThread(Thread, KeGetCurrentPrcb());
368 
369  /* Check if were swapped ok */
370  if (WaitStatus != STATUS_KERNEL_APC)
371  {
372  /* This is a good thing */
373  if (WaitStatus == STATUS_TIMEOUT) WaitStatus = STATUS_SUCCESS;
374 
375  /* Return Status */
376  return WaitStatus;
377  }
378 
379  /* Recalculate due times */
380  Interval = KiRecalculateDueTime(OriginalDueTime,
381  &DueTime,
382  &NewDueTime);
383  }
384 
385 WaitStart:
386  /* Setup a new wait */
387  Thread->WaitIrql = KeRaiseIrqlToSynchLevel();
390  }
391 
392  /* We're done! */
393  KiReleaseDispatcherLock(Thread->WaitIrql);
394  return WaitStatus;
395 
396 NoWait:
397  /* There was nothing to wait for. Did we have a wait interval? */
398  if (!Interval->QuadPart)
399  {
400  /* Unlock the dispatcher and do a yield */
401  KiReleaseDispatcherLock(Thread->WaitIrql);
402  return NtYieldExecution();
403  }
404 
405  /* Unlock the dispatcher and adjust the quantum for a no-wait */
408  return STATUS_SUCCESS;
409 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:452
#define TRUE
Definition: types.h:120
#define KxDelayThreadWait()
Definition: ke_x.h:1067
_In_ LARGE_INTEGER DueTime
Definition: kefuncs.h:524
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
VOID NTAPI KiAdjustQuantumThread(IN PKTHREAD Thread)
Definition: thrdschd.c:461
#define TIMER_WAIT_BLOCK
Definition: ke.h:162
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_WAIT_0
Definition: ntstatus.h:223
#define KiAddThreadToWaitList(Thread, Swappable)
Definition: ke_x.h:816
unsigned char BOOLEAN
FORCEINLINE VOID KxInsertTimer(IN PKTIMER Timer, IN ULONG Hand)
Definition: ke_x.h:915
#define STATUS_KERNEL_APC
Definition: ntstatus.h:79
DWORD Interval
Definition: netstat.c:30
NTSTATUS NTAPI NtYieldExecution(VOID)
Definition: thrdschd.c:744
uint64_t ULONGLONG
Definition: typedefs.h:65
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NTSTATUS
Definition: precomp.h:20
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE PLARGE_INTEGER KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime, IN PLARGE_INTEGER DueTime, IN OUT PLARGE_INTEGER NewDueTime)
Definition: ke_x.h:777
UINT Timer
Definition: capclock.c:11
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: thrdschd.c:355
VOID FASTCALL KiActivateWaiterQueue(IN PKQUEUE Queue)
Definition: queue.c:24
FORCEINLINE VOID KiReleaseDispatcherLockFromDpcLevel(VOID)
Definition: ke_x.h:168
unsigned int ULONG
Definition: retypes.h:1
#define KeGetCurrentThread
Definition: hal.h:44
FORCEINLINE NTSTATUS KiCheckAlertability(IN PKTHREAD Thread, IN BOOLEAN Alertable, IN KPROCESSOR_MODE WaitMode)
Definition: ke_x.h:833
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define APC_LEVEL
Definition: env_spec_w32.h:695
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
FORCEINLINE VOID KiAcquireDispatcherLockAtDpcLevel(VOID)
Definition: ke_x.h:160
LONGLONG QuadPart
Definition: typedefs.h:112
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156

Referenced by BootLogoFadeIn(), ClassSendSrbSynchronous(), ConMgrWriteData(), DisplayBootBitmap(), DriverEntry(), ExpAllocateExclusiveWaiterEvent(), ExpAllocateSharedWaiterSemaphore(), Ext2Sleep(), FatPagingFileIo(), fcbopen_main(), CUSBHardwareDevice::GlobalReset(), HwSeek(), InbvRotationThread(), IoCancelThreadIo(), IopAbortInterruptedIrp(), IopAllocateIrpMustSucceed(), KiInitMachineDependent(), LpcpDeletePort(), MonitorThread(), nfs41_Lock(), NtCancelIoFile(), NtDelayExecution(), PciStallForPowerChange(), PspExitThread(), ScsiClassSendSrbSynchronous(), SleepMs(), CUSBHardwareDevice::StartController(), TestCreateNamedPipe(), TestEventConcurrent(), UDFCommonShutdown(), UDFDoDismountSequence(), UDFDriverUnload(), UDFEjectReqWaiter(), UDFMountVolume(), UDFRecoverFromError(), UDFReleaseVCB(), USBH_Wait(), USBPORT_Wait(), and WaitForHwAddress().

◆ KeIsWaitListEmpty()

BOOLEAN NTAPI KeIsWaitListEmpty ( IN PVOID  Object)

Definition at line 272 of file wait.c.

273 {
275  return FALSE;
276 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ KeWaitForMultipleObjects()

NTSTATUS NTAPI KeWaitForMultipleObjects ( IN ULONG  Count,
IN PVOID  Object[],
IN WAIT_TYPE  WaitType,
IN KWAIT_REASON  WaitReason,
IN KPROCESSOR_MODE  WaitMode,
IN BOOLEAN  Alertable,
IN PLARGE_INTEGER Timeout  OPTIONAL,
OUT PKWAIT_BLOCK WaitBlockArray  OPTIONAL 
)

Definition at line 586 of file wait.c.

594 {
595  PKMUTANT CurrentObject;
596  PKWAIT_BLOCK WaitBlock;
598  PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
599  PKTIMER Timer = &Thread->Timer;
600  NTSTATUS WaitStatus = STATUS_SUCCESS;
601  BOOLEAN Swappable;
602  PLARGE_INTEGER OriginalDueTime = Timeout;
603  LARGE_INTEGER DueTime = {{0}}, NewDueTime, InterruptTime;
604  ULONG Index, Hand = 0;
605 
606  if (Thread->WaitNext)
608  else if (KeGetCurrentIrql() == DISPATCH_LEVEL &&
609  (!Timeout || Timeout->QuadPart != 0))
610  {
611  /* HACK: tcpip is broken and waits with spinlocks acquired (CORE-6473) */
612  DPRINT("%s called at DISPATCH_LEVEL with non-zero timeout!\n",
613  __FUNCTION__);
614  }
615  else
617 
618  /* Make sure the Wait Count is valid */
619  if (!WaitBlockArray)
620  {
621  /* Check in regards to the Thread Object Limit */
623  {
624  /* Bugcheck */
625  KeBugCheck(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
626  }
627 
628  /* Use the Thread's Wait Block */
629  WaitBlockArray = &Thread->WaitBlock[0];
630  }
631  else
632  {
633  /* Using our own Block Array, so check with the System Object Limit */
635  {
636  /* Bugcheck */
637  KeBugCheck(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
638  }
639  }
640 
641  /* Sanity check */
642  ASSERT(Count != 0);
643 
644  /* Check if the lock is already held */
645  if (!Thread->WaitNext) goto WaitStart;
646 
647  /* Otherwise, we already have the lock, so initialize the wait */
648  Thread->WaitNext = FALSE;
649  /* Note that KxMultiThreadWait is a macro, defined in ke_x.h, that */
650  /* uses (and modifies some of) the following local */
651  /* variables: */
652  /* Thread, Index, WaitBlock, Timer, Timeout, Hand and Swappable. */
653  /* If it looks like this code doesn't actually wait for any objects */
654  /* at all, it's because the setup is done by that macro. */
656 
657  /* Start wait loop */
658  for (;;)
659  {
660  /* Disable pre-emption */
661  Thread->Preempted = FALSE;
662 
663  /* Check if a kernel APC is pending and we're below APC_LEVEL */
664  if ((Thread->ApcState.KernelApcPending) && !(Thread->SpecialApcDisable) &&
665  (Thread->WaitIrql < APC_LEVEL))
666  {
667  /* Unlock the dispatcher */
668  KiReleaseDispatcherLock(Thread->WaitIrql);
669  }
670  else
671  {
672  /* Check what kind of wait this is */
673  Index = 0;
674  if (WaitType == WaitAny)
675  {
676  /* Loop blocks */
677  do
678  {
679  /* Get the Current Object */
680  CurrentObject = (PKMUTANT)Object[Index];
681  ASSERT(CurrentObject->Header.Type != QueueObject);
682 
683  /* Check if the Object is a mutant */
684  if (CurrentObject->Header.Type == MutantObject)
685  {
686  /* Check if it's signaled */
687  if ((CurrentObject->Header.SignalState > 0) ||
688  (Thread == CurrentObject->OwnerThread))
689  {
690  /* This is a Wait Any, so unwait this and exit */
691  if (CurrentObject->Header.SignalState !=
692  (LONG)MINLONG)
693  {
694  /* Normal signal state, unwait it and return */
695  KiSatisfyMutantWait(CurrentObject, Thread);
696  WaitStatus = (NTSTATUS)Thread->WaitStatus | Index;
697  goto DontWait;
698  }
699  else
700  {
701  /* Raise an exception (see wasm.ru) */
702  KiReleaseDispatcherLock(Thread->WaitIrql);
704  }
705  }
706  }
707  else if (CurrentObject->Header.SignalState > 0)
708  {
709  /* Another signaled object, unwait and return */
710  KiSatisfyNonMutantWait(CurrentObject);
711  WaitStatus = Index;
712  goto DontWait;
713  }
714 
715  /* Go to the next block */
716  Index++;
717  } while (Index < Count);
718  }
719  else
720  {
721  /* Loop blocks */
722  do
723  {
724  /* Get the Current Object */
725  CurrentObject = (PKMUTANT)Object[Index];
726  ASSERT(CurrentObject->Header.Type != QueueObject);
727 
728  /* Check if we're dealing with a mutant again */
729  if (CurrentObject->Header.Type == MutantObject)
730  {
731  /* Check if it has an invalid count */
732  if ((Thread == CurrentObject->OwnerThread) &&
733  (CurrentObject->Header.SignalState == (LONG)MINLONG))
734  {
735  /* Raise an exception */
736  KiReleaseDispatcherLock(Thread->WaitIrql);
738  }
739  else if ((CurrentObject->Header.SignalState <= 0) &&
740  (Thread != CurrentObject->OwnerThread))
741  {
742  /* We don't own it, can't satisfy the wait */
743  break;
744  }
745  }
746  else if (CurrentObject->Header.SignalState <= 0)
747  {
748  /* Not signaled, can't satisfy */
749  break;
750  }
751 
752  /* Go to the next block */
753  Index++;
754  } while (Index < Count);
755 
756  /* Check if we've went through all the objects */
757  if (Index == Count)
758  {
759  /* Loop wait blocks */
760  WaitBlock = WaitBlockArray;
761  do
762  {
763  /* Get the object and satisfy it */
764  CurrentObject = (PKMUTANT)WaitBlock->Object;
765  KiSatisfyObjectWait(CurrentObject, Thread);
766 
767  /* Go to the next block */
768  WaitBlock = WaitBlock->NextWaitBlock;
769  } while(WaitBlock != WaitBlockArray);
770 
771  /* Set the wait status and get out */
772  WaitStatus = (NTSTATUS)Thread->WaitStatus;
773  goto DontWait;
774  }
775  }
776 
777  /* Make sure we can satisfy the Alertable request */
778  WaitStatus = KiCheckAlertability(Thread, Alertable, WaitMode);
779  if (WaitStatus != STATUS_WAIT_0) break;
780 
781  /* Enable the Timeout Timer if there was any specified */
782  if (Timeout)
783  {
784  /* Check if the timer expired */
785  InterruptTime.QuadPart = KeQueryInterruptTime();
786  if ((ULONGLONG)InterruptTime.QuadPart >=
787  Timer->DueTime.QuadPart)
788  {
789  /* It did, so we don't need to wait */
790  WaitStatus = STATUS_TIMEOUT;
791  goto DontWait;
792  }
793 
794  /* It didn't, so activate it */
795  Timer->Header.Inserted = TRUE;
796 
797  /* Link the wait blocks */
798  WaitBlock->NextWaitBlock = TimerBlock;
799  }
800 
801  /* Insert into Object's Wait List*/
802  WaitBlock = WaitBlockArray;
803  do
804  {
805  /* Get the Current Object */
806  CurrentObject = WaitBlock->Object;
807 
808  /* Link the Object to this Wait Block */
809  InsertTailList(&CurrentObject->Header.WaitListHead,
810  &WaitBlock->WaitListEntry);
811 
812  /* Move to the next Wait Block */
813  WaitBlock = WaitBlock->NextWaitBlock;
814  } while (WaitBlock != WaitBlockArray);
815 
816  /* Handle Kernel Queues */
817  if (Thread->Queue) KiActivateWaiterQueue(Thread->Queue);
818 
819  /* Setup the wait information */
820  Thread->State = Waiting;
821 
822  /* Add the thread to the wait list */
823  KiAddThreadToWaitList(Thread, Swappable);
824 
825  /* Activate thread swap */
826  ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);
828 
829  /* Check if we have a timer */
830  if (Timeout)
831  {
832  /* Insert it */
833  KxInsertTimer(Timer, Hand);
834  }
835  else
836  {
837  /* Otherwise, unlock the dispatcher */
839  }
840 
841  /* Swap the thread */
842  WaitStatus = (NTSTATUS)KiSwapThread(Thread, KeGetCurrentPrcb());
843 
844  /* Check if we were executing an APC */
845  if (WaitStatus != STATUS_KERNEL_APC) return WaitStatus;
846 
847  /* Check if we had a timeout */
848  if (Timeout)
849  {
850  /* Recalculate due times */
851  Timeout = KiRecalculateDueTime(OriginalDueTime,
852  &DueTime,
853  &NewDueTime);
854  }
855  }
856 
857 WaitStart:
858  /* Setup a new wait */
859  Thread->WaitIrql = KeRaiseIrqlToSynchLevel();
862  }
863 
864  /* We are done */
865  KiReleaseDispatcherLock(Thread->WaitIrql);
866  return WaitStatus;
867 
868 DontWait:
869  /* Release dispatcher lock but maintain high IRQL */
871 
872  /* Adjust the Quantum and return the wait status */
874  return WaitStatus;
875 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:452
#define TRUE
Definition: types.h:120
#define KiSatisfyNonMutantWait(Object)
Definition: ke_x.h:741
LIST_ENTRY WaitListEntry
Definition: ketypes.h:444
_In_ LARGE_INTEGER DueTime
Definition: kefuncs.h:524
#define KiSatisfyMutantWait(Object, Thread)
Definition: ke_x.h:707
#define MAXIMUM_WAIT_OBJECTS
Definition: winbase.h:385
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
VOID NTAPI KiAdjustQuantumThread(IN PKTHREAD Thread)
Definition: thrdschd.c:461
#define ExRaiseStatus
Definition: ntoskrnl.h:95
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define InsertTailList(ListHead, Entry)
#define TIMER_WAIT_BLOCK
Definition: ke.h:162
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
struct _KMUTANT * PKMUTANT
#define STATUS_WAIT_0
Definition: ntstatus.h:223
long LONG
Definition: pedump.c:60
#define KiAddThreadToWaitList(Thread, Swappable)
Definition: ke_x.h:816
unsigned char BOOLEAN
void DPRINT(...)
Definition: polytest.cpp:61
DISPATCHER_HEADER Header
Definition: ketypes.h:829
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1469
FORCEINLINE VOID KxInsertTimer(IN PKTIMER Timer, IN ULONG Hand)
Definition: ke_x.h:915
#define STATUS_KERNEL_APC
Definition: ntstatus.h:79
WaitType
Definition: shlextdbg.cpp:19
uint64_t ULONGLONG
Definition: typedefs.h:65
PVOID Object
Definition: ketypes.h:456
static const UCHAR Index[8]
Definition: usbohci.c:18
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
static IUnknown Object
Definition: main.c:512
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NTSTATUS
Definition: precomp.h:20
#define MINLONG
Definition: umtypes.h:115
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE PLARGE_INTEGER KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime, IN PLARGE_INTEGER DueTime, IN OUT PLARGE_INTEGER NewDueTime)
Definition: ke_x.h:777
static ULONG Timeout
Definition: ping.c:61
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
#define KxMultiThreadWait()
Definition: ke_x.h:1098
LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: thrdschd.c:355
VOID FASTCALL KiActivateWaiterQueue(IN PKQUEUE Queue)
Definition: queue.c:24
#define KiSatisfyObjectWait(Object, Thread)
Definition: ke_x.h:759
FORCEINLINE VOID KiReleaseDispatcherLockFromDpcLevel(VOID)
Definition: ke_x.h:168
struct _KTHREAD *RESTRICTED_POINTER OwnerThread
Definition: ketypes.h:831
unsigned int ULONG
Definition: retypes.h:1
_Must_inspect_result_ _In_ WAIT_TYPE _In_opt_ PLARGE_INTEGER _In_opt_ PKWAIT_BLOCK WaitBlockArray
Definition: fsrtlfuncs.h:1151
LIST_ENTRY WaitListHead
Definition: ketypes.h:796
#define KeGetCurrentThread
Definition: hal.h:44
FORCEINLINE NTSTATUS KiCheckAlertability(IN PKTHREAD Thread, IN BOOLEAN Alertable, IN KPROCESSOR_MODE WaitMode)
Definition: ke_x.h:833
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define __FUNCTION__
Definition: types.h:112
#define APC_LEVEL
Definition: env_spec_w32.h:695
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
#define STATUS_MUTANT_LIMIT_EXCEEDED
Definition: ntstatus.h:620
#define THREAD_WAIT_OBJECTS
Definition: ketypes.h:480
FORCEINLINE VOID KiAcquireDispatcherLockAtDpcLevel(VOID)
Definition: ke_x.h:160
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156

Referenced by co_MsqSendMessage(), ExpWorkerThreadBalanceManager(), KeBalanceSetManager(), MiBalancerThread(), MmZeroPageThread(), NtUserWaitForInputIdle(), NtWaitForMultipleObjects(), PipeWorkerThread(), QueueThread(), RawInputThreadMain(), ReadBytes(), sys_arch_mbox_fetch(), sys_arch_sem_wait(), TdiCall(), TdiSendThread(), TestEventConcurrent(), and WaitForEventSafely().

◆ KeWaitForSingleObject()

NTSTATUS NTAPI KeWaitForSingleObject ( IN PVOID  Object,
IN KWAIT_REASON  WaitReason,
IN KPROCESSOR_MODE  WaitMode,
IN BOOLEAN  Alertable,
IN PLARGE_INTEGER Timeout  OPTIONAL 
)

Definition at line 416 of file wait.c.

421 {
423  PKMUTANT CurrentObject = (PKMUTANT)Object;
424  PKWAIT_BLOCK WaitBlock = &Thread->WaitBlock[0];
425  PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
426  PKTIMER Timer = &Thread->Timer;
427  NTSTATUS WaitStatus;
428  BOOLEAN Swappable;
429  LARGE_INTEGER DueTime = {{0}}, NewDueTime, InterruptTime;
430  PLARGE_INTEGER OriginalDueTime = Timeout;
431  ULONG Hand = 0;
432 
433  if (Thread->WaitNext)
435  else
438  Timeout && Timeout->QuadPart == 0));
439 
440  /* Check if the lock is already held */
441  if (!Thread->WaitNext) goto WaitStart;
442 
443  /* Otherwise, we already have the lock, so initialize the wait */
444  Thread->WaitNext = FALSE;
446 
447  /* Start wait loop */
448  for (;;)
449  {
450  /* Disable pre-emption */
451  Thread->Preempted = FALSE;
452 
453  /* Check if a kernel APC is pending and we're below APC_LEVEL */
454  if ((Thread->ApcState.KernelApcPending) && !(Thread->SpecialApcDisable) &&
455  (Thread->WaitIrql < APC_LEVEL))
456  {
457  /* Unlock the dispatcher */
458  KiReleaseDispatcherLock(Thread->WaitIrql);
459  }
460  else
461  {
462  /* Sanity check */
463  ASSERT(CurrentObject->Header.Type != QueueObject);
464 
465  /* Check if it's a mutant */
466  if (CurrentObject->Header.Type == MutantObject)
467  {
468  /* Check its signal state or if we own it */
469  if ((CurrentObject->Header.SignalState > 0) ||
470  (Thread == CurrentObject->OwnerThread))
471  {
472  /* Just unwait this guy and exit */
473  if (CurrentObject->Header.SignalState != (LONG)MINLONG)
474  {
475  /* It has a normal signal state. Unwait and return */
476  KiSatisfyMutantWait(CurrentObject, Thread);
477  WaitStatus = (NTSTATUS)Thread->WaitStatus;
478  goto DontWait;
479  }
480  else
481  {
482  /* Raise an exception */
483  KiReleaseDispatcherLock(Thread->WaitIrql);
485  }
486  }
487  }
488  else if (CurrentObject->Header.SignalState > 0)
489  {
490  /* Another satisfied object */
491  KiSatisfyNonMutantWait(CurrentObject);
492  WaitStatus = STATUS_WAIT_0;
493  goto DontWait;
494  }
495 
496  /* Make sure we can satisfy the Alertable request */
497  WaitStatus = KiCheckAlertability(Thread, Alertable, WaitMode);
498  if (WaitStatus != STATUS_WAIT_0) break;
499 
500  /* Enable the Timeout Timer if there was any specified */
501  if (Timeout)
502  {
503  /* Check if the timer expired */
504  InterruptTime.QuadPart = KeQueryInterruptTime();
505  if ((ULONGLONG)InterruptTime.QuadPart >=
506  Timer->DueTime.QuadPart)
507  {
508  /* It did, so we don't need to wait */
509  WaitStatus = STATUS_TIMEOUT;
510  goto DontWait;
511  }
512 
513  /* It didn't, so activate it */
514  Timer->Header.Inserted = TRUE;
515  }
516 
517  /* Link the Object to this Wait Block */
518  InsertTailList(&CurrentObject->Header.WaitListHead,
519  &WaitBlock->WaitListEntry);
520 
521  /* Handle Kernel Queues */
522  if (Thread->Queue) KiActivateWaiterQueue(Thread->Queue);
523 
524  /* Setup the wait information */
525  Thread->State = Waiting;
526 
527  /* Add the thread to the wait list */
528  KiAddThreadToWaitList(Thread, Swappable);
529 
530  /* Activate thread swap */
531  ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);
533 
534  /* Check if we have a timer */
535  if (Timeout)
536  {
537  /* Insert it */
538  KxInsertTimer(Timer, Hand);
539  }
540  else
541  {
542  /* Otherwise, unlock the dispatcher */
544  }
545 
546  /* Do the actual swap */
547  WaitStatus = (NTSTATUS)KiSwapThread(Thread, KeGetCurrentPrcb());
548 
549  /* Check if we were executing an APC */
550  if (WaitStatus != STATUS_KERNEL_APC) return WaitStatus;
551 
552  /* Check if we had a timeout */
553  if (Timeout)
554  {
555  /* Recalculate due times */
556  Timeout = KiRecalculateDueTime(OriginalDueTime,
557  &DueTime,
558  &NewDueTime);
559  }
560  }
561 WaitStart:
562  /* Setup a new wait */
563  Thread->WaitIrql = KeRaiseIrqlToSynchLevel();
566  }
567 
568  /* Wait complete */
569  KiReleaseDispatcherLock(Thread->WaitIrql);
570  return WaitStatus;
571 
572 DontWait:
573  /* Release dispatcher lock but maintain high IRQL */
575 
576  /* Adjust the Quantum and return the wait status */
578  return WaitStatus;
579 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:452
#define TRUE
Definition: types.h:120
#define KiSatisfyNonMutantWait(Object)
Definition: ke_x.h:741
LIST_ENTRY WaitListEntry
Definition: ketypes.h:444
_In_ LARGE_INTEGER DueTime
Definition: kefuncs.h:524
#define KiSatisfyMutantWait(Object, Thread)
Definition: ke_x.h:707
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
VOID NTAPI KiAdjustQuantumThread(IN PKTHREAD Thread)
Definition: thrdschd.c:461
#define ExRaiseStatus
Definition: ntoskrnl.h:95
#define KxSingleThreadWait()
Definition: ke_x.h:1154
#define InsertTailList(ListHead, Entry)
#define TIMER_WAIT_BLOCK
Definition: ke.h:162
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
struct _KMUTANT * PKMUTANT
#define STATUS_WAIT_0
Definition: ntstatus.h:223
long LONG
Definition: pedump.c:60
#define KiAddThreadToWaitList(Thread, Swappable)
Definition: ke_x.h:816
unsigned char BOOLEAN
DISPATCHER_HEADER Header
Definition: ketypes.h:829
FORCEINLINE VOID KxInsertTimer(IN PKTIMER Timer, IN ULONG Hand)
Definition: ke_x.h:915
#define STATUS_KERNEL_APC
Definition: ntstatus.h:79
uint64_t ULONGLONG
Definition: typedefs.h:65
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
static IUnknown Object
Definition: main.c:512
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NTSTATUS
Definition: precomp.h:20
#define MINLONG
Definition: umtypes.h:115
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE PLARGE_INTEGER KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime, IN PLARGE_INTEGER DueTime, IN OUT PLARGE_INTEGER NewDueTime)
Definition: ke_x.h:777
static ULONG Timeout
Definition: ping.c:61
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: thrdschd.c:355
VOID FASTCALL KiActivateWaiterQueue(IN PKQUEUE Queue)
Definition: queue.c:24
FORCEINLINE VOID KiReleaseDispatcherLockFromDpcLevel(VOID)
Definition: ke_x.h:168
struct _KTHREAD *RESTRICTED_POINTER OwnerThread
Definition: ketypes.h:831
unsigned int ULONG
Definition: retypes.h:1
LIST_ENTRY WaitListHead
Definition: ketypes.h:796
#define KeGetCurrentThread
Definition: hal.h:44
FORCEINLINE NTSTATUS KiCheckAlertability(IN PKTHREAD Thread, IN BOOLEAN Alertable, IN KPROCESSOR_MODE WaitMode)
Definition: ke_x.h:833
#define APC_LEVEL
Definition: env_spec_w32.h:695
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
#define STATUS_MUTANT_LIMIT_EXCEEDED
Definition: ntstatus.h:620
FORCEINLINE VOID KiAcquireDispatcherLockAtDpcLevel(VOID)
Definition: ke_x.h:160
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156

Referenced by _Function_class_(), _In_reads_(), _KsEdit(), _MiSimpleWrite(), _Requires_lock_held_(), _Success_(), acpi_bus_receive_event(), AcpiOsWaitSemaphore(), AcquireMutexThread(), AcquireResourceThread(), BatteryClassIoctl(), BatteryIoctl(), BehaviorChecks(), BindAdapterByName(), Bus_GetDeviceCapabilities(), Bus_SendIrpSynchronously(), calc_csum(), CalculateMbrCheckSum(), CallUSBD(), CcCanIWrite(), CcpMapData(), CcpReferenceCacheExclusive(), CcReadVirtualAddress(), CcWaitForCurrentLazyWriterActivity(), CcWriteVirtualAddress(), CcZeroData(), CdHijackIrpAndFlushDevice(), CdPerformDevIoCtrlEx(), CdReadSectors(), CdRomDeviceControl(), CdRomDeviceControlDispatch(), CdRomIsPlayActive(), CdRomUpdateMmcDriveCapabilities(), CdWaitSync(), check_csum(), ChewShutdown(), chunk_lock_range(), ClassAcquireChildLock(), ClassClaimDevice(), ClassDeviceControl(), ClassDispatchPnp(), ClassModeSense(), ClasspCleanupProtectedLocks(), ClasspCreateClose(), ClasspEjectionControl(), ClasspFailurePredict(), ClasspInitializeGesn(), ClassReadDriveCapacity(), ClassRemoveDevice(), ClassSendIrpSynchronous(), ClassSendSrbSynchronous(), ClassSetFailurePredictionPoll(), clean_space_cache(), CleanupTest(), CmBattGetAcpiInterfaces(), CmBattPnpDispatch(), CmBattSendDownStreamIrp(), CmpInitializeHiveList(), CmpOpenHiveFiles(), co_MsqWaitForNewMessages(), ConMgrWorkerProcessEvents(), ConnectPortDriver(), CountThread(), CreateDMA(), CreateRemoteDatabase(), CTEBlock(), DbgkpQueueMessage(), DestroyPortDriver(), dev_ioctl(), DeviceIoControl(), DiskAcquirePartitioningLock(), DiskDeviceControl(), DiskPerformSmartCommand(), DiskSendFailurePredictIoctl(), DiskStartFdo(), DLDpWaitForResource(), do_tree_writes(), DoRebootCommand(), DriverEntry(), DriverIoControl(), EngpFileIoRequest(), EngWaitForSingleObject(), ExAcquireFastMutex(), ExfWaitForRundownProtectionRelease(), ExfWaitForRundownProtectionReleaseCacheAware(), ExpWaitForResource(), ExpWorkerThreadBalanceManager(), ExSwapinWorkerThreads(), Ext2bhReaperThread(), Ext2DiskIoControl(), Ext2DiskShutDown(), Ext2FcbReaperThread(), Ext2IsMediaWriteProtected(), Ext2McbReaperThread(), Ext2MediaEjectControl(), Ext2ReadSync(), Ext2ReadWriteBlocks(), Ext2StartReaper(), Ext2StopReaper(), Ext2SyncUninitializeCacheMap(), ExTimedWaitForUnblockPushLock(), ExUnregisterCallback(), FatHijackIrpAndFlushDevice(), FatIsMediaWriteProtected(), FatPagingFileIo(), FatPerformDevIoCtrl(), FatPerformVerifyDiskRead(), FatSyncUninitializeCacheMap(), FatToggleMediaEjectDisable(), FatWaitSync(), FDO_QueryCapabilities(), FFSDiskIoControl(), FFSDiskShutDown(), FFSGetPartition(), FFSIsMediaWriteProtected(), FFSMediaEjectControl(), FFSReadSync(), FFSReadWriteBlocks(), FFSSyncUninitializeCacheMap(), FilterDispatch_fnClose(), FinishThread(), FlopticalFormatMedia(), flush_disk_caches(), ForwardIrpAndWait(), ForwardIrpSynchronous(), FreeBT_DispatchDevCtrl(), FreeBT_DispatchRead(), FreeBT_DispatchWrite(), FreeBT_GetPortStatus(), FreeBT_ResetParentPort(), FreeDeviceData(), FsRecGetDeviceSectors(), FsRecGetDeviceSectorSize(), FsRecLoadFileSystem(), FsRecReadBlock(), FsRtlBalanceReads(), FsRtlDeregisterUncProvider(), FsRtlGetFileSize(), FsRtlpPostStackOverflow(), FsRtlRegisterUncProvider(), FsRtlWaitOnIrp(), FstubGetDiskGeometry(), FstubReadSector(), FstubWriteSector(), GetBusInterface(), GetDeviceId(), GreenDeviceIoControl(), HalGetAdapter(), HaliRegisterBusHandler(), HalpGetFullGeometry(), HalpGrowMapBufferWorker(), HalPutDmaAdapter(), HalpXboxReadSector(), HandleCancelRemoveDevice(), HandleCancelStopDevice(), HandleQueryCapabilities(), HandleQueryRemoveDevice(), HandleQueryStopDevice(), HandleRemoveDevice(), HandleStartDevice(), HandleStopDevice(), HandleSurpriseRemoval(), HDA_SendVerbs(), Hid_DispatchUrb(), HidClass_Close(), HidClass_DeviceControl(), HidClass_Write(), HidClassFDO_DispatchRequestSynchronous(), HidClassFDO_QueryCapabilities(), HidPnp(), HidUsb_GetPortStatus(), HidUsb_ResetPort(), HoldIoRequestsWorkerRoutine(), i8042SendHookWorkItem(), IdleNotificationCallback(), IKsDevice_fnAcquireDevice(), IKsFilter_DispatchCreatePin(), IKsFilter_DispatchDeviceIoControl(), IKsFilter_fnAddProcessPin(), IKsFilter_fnRemoveProcessPin(), IKsPin_PinAllocatorFramingPropertyHandler(), IKsPin_PinDataFormatPropertyHandler(), IKsPin_PinStatePropertyHandler(), IKsProcessingObject_fnProcessingObjectWork(), IKsProcessingObject_fnReset(), InitializeDeviceData(), InitializeFilterWithKs(), IntCreateWindowStation(), IntVideoPortForwardIrpAndWait(), IoCancelFileOpen(), IoForwardIrpSynchronously(), IoGetBootDiskInformation(), IopAbortInterruptedIrp(), IopAcquireFileObjectLock(), IopAllocateReserveIrp(), IopCloseFile(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopDeleteFile(), IopFinalizeAsynchronousIo(), IopGetFileInformation(), IopGetSetSecurityObject(), IopInitiatePnpIrp(), IopLoadFileSystemDriver(), IopLoadUnloadDriver(), IopMountVolume(), IopParseDevice(), IopPerformSynchronousRequest(), IopQueryDeviceInformation(), IopShutdownBaseFileSystems(), IopSynchronousCall(), IoReleaseRemoveLockAndWaitEx(), IoReportTargetDeviceChange(), IoSetInformation(), IoShutdownSystem(), IoVerifyVolume(), IoVolumeDeviceToDosName(), IsaForwardIrpSynchronous(), IsFtVolume(), IssueUniqueIdChangeNotify(), IsThisASanyo(), KbdHid_Close(), KbdHid_Create(), KbdHid_Pnp(), KbdHid_SubmitRequest(), KdpLoggerThread(), KeyboardDeviceWorker(), KiAcquireFastMutex(), KiSuspendThread(), KmtFinishThread(), KmtUserModeCallback(), KsAcquireControl(), KsAddItemToObjectBag(), KsCopyObjectBagItems(), KsFilterAcquireProcessingMutex(), KsFreeObjectBag(), KsInstallBusEnumInterface(), KspDeviceSetGetBusData(), KspForwardIrpSynchronous(), KsPinAcquireProcessingMutex(), KspSynchronizedEventRoutine(), KsQueryInformationFile(), KsReadFile(), KsRemoveBusEnumInterface(), KsRemoveItemFromObjectBag(), KsSetInformationFile(), KsSynchronousIoControlDevice(), KsUnregisterWorker(), KsWriteFile(), LANRegisterAdapter(), LANUnregisterAdapter(), MiDereferenceSessionFinal(), MiDispatchFault(), MiniQueryInformation(), MiniSetInformation(), MiReadFilePage(), MiReadPageFile(), MiSimpleRead(), MmAddVerifierThunks(), MmLoadSystemImage(), MmNotPresentFaultCacheSectionInner(), MmpSectionAccessFaultInner(), MmRequestPageMemoryConsumer(), MmUnloadSystemImage(), MmWriteToSwapPage(), MouHid_Close(), MouHid_Create(), MouHid_Pnp(), MouHid_SubmitRequest(), MountMgrDeviceControl(), MountMgrMountedDeviceArrival(), MountMgrMountedDeviceRemoval(), MountMgrNotifyNameChange(), MountMgrQueryDosVolumePaths(), MountMgrShutdown(), MountMgrUniqueIdChangeRoutine(), MountMgrUnload(), MsfsWrite(), NDISCall(), NdisIForwardIrpAndWait(), NdisMAllocateMapRegisters(), NdisMSetupDmaTransfer(), NdisMSleep(), NdisWaitEvent(), NduDispatchRead(), NduDispatchWrite(), NduReceive(), nfs41_upcall(), nfs41_UpcallWaitForReply(), NtfsDeviceIoControl(), NtfsReadDisk(), NtfsWriteDisk(), NtGetPlugPlayEvent(), NtQueryInformationFile(), NtSecureConnectPort(), NtSetHighWaitLowEventPair(), NtSetInformationFile(), NtSetLowWaitHighEventPair(), NtSignalAndWaitForSingleObject(), NtStartProfile(), NtStopProfile(), NtWaitForDebugEvent(), NtWaitForSingleObject(), NtWaitHighEventPair(), NtWaitLowEventPair(), PageFileBehaviorChecks(), PcForwardIrpSynchronous(), PciAssignSlotResources(), PciCallDownIrpStack(), PciFindParentPciFdoExtension(), PciFindPdoByFunction(), PciFindPdoByLocation(), PciGetDeviceCapabilities(), PciInsertEntryAtHead(), PciInsertEntryAtTail(), PciQueryForPciBusInterface(), PciScanBus(), PciSendIoctl(), PcRequestNewPowerState(), PiceSendIoctl(), PopAddRemoveSysCapsCallback(), PopFlushVolumes(), PopProcessShutDownLists(), PopSendQuerySystemPowerState(), PopSendSetSystemPowerState(), PsGetContextThread(), PspExitThread(), PsSetContextThread(), QueryAdapterOid(), QueryBusInterface(), QueryDeviceInformation(), QueryInterface(), QuerySuggestedLinkName(), RamdiskPnp(), RawCleanup(), RawClose(), RawCreate(), RawFileSystemControl(), RawQueryFsSizeInfo(), RawUserFsCtrl(), read_data(), read_send_buffer(), ReadBytes(), ReconcileThisDatabaseWithMasterWorker(), RemoveWorkItem(), RfsdDiskIoControl(), RfsdDiskShutDown(), RfsdIsMediaWriteProtected(), RfsdMediaEjectControl(), RfsdReadSync(), RfsdReadWriteBlocks(), RfsdSyncUninitializeCacheMap(), RootHubInitCallbackFunction(), RxConstructNetRoot(), RxConstructSrvCall(), RxPurgeRelatedFobxs(), RxScavengeFobxsForNetRoot(), RxSpinUpRequestsDispatcher(), RxUninitializeCacheMap(), SacAcquireLock(), SacAcquireMutexLock(), scrub_chunk_raid56_stripe_run(), scrub_extent(), ScsiClassClaimDevice(), ScsiClassGetCapabilities(), ScsiClassGetInquiryData(), ScsiClassSendSrbSynchronous(), ScsiDiskDeviceControl(), ScsiFlopStartDevice(), send_disks_pnp_message(), SendFragments(), SendLinkCreated(), SendLinkDeleted(), SendOnlineNotification(), SermouseDeviceIoControl(), SermouseDeviceWorker(), SetAdapterOid(), snapshot_tree_copy(), SpiSendInquiry(), StartMotor(), StartThread(), StreamClassReadWriteConfig(), StreamClassReenumerateStreams(), StreamClassStartDevice(), SubmitRequestToRootHub(), SubmitUrbSync(), sync_read_phys(), SyncForwardIrp(), sys_shutdown(), SystemProcessTest(), TcpipWaitForSingleObject(), TCPSleep(), TdiCall(), TdiUnload(), TestEventScheduling(), TestFastMutexConcurrent(), TestGuardedMutexConcurrent(), TestIrpHandler(), TestMutex(), TestOwnerRes(), TestPoRequestPowerIrp(), TestProviderInfo(), TestResourceWithThreads(), TestTcpConnect(), TriggerWork(), try_consolidation(), UDFEjectReqWaiter(), UDFPnpQueryRemove(), UDFPnpRemove(), UDFPnpSurpriseRemove(), UDFStopEjectWaiter(), UnbindAdapterByContext(), uninit(), Unload(), USBCCGP_QueryInterface(), USBCCGP_SyncForwardIrp(), USBCCGP_SyncUrbRequest(), USBD_UnRegisterRootHubCallBack(), USBH_AbortInterruptPipe(), USBH_ChangeIndicationWorker(), USBH_CheckHubIdle(), USBH_CheckIdleAbort(), USBH_EnableParentPort(), USBH_FdoCleanup(), USBH_FdoIdleNotificationCallback(), USBH_FdoPnP(), USBH_FdoPower(), USBH_FdoQueryBusRelations(), USBH_FlushPortPwrList(), USBH_GetPortStatus(), USBH_HubSetD0(), USBH_PdoIoctlGetPortStatus(), USBH_QueryCapabilities(), USBH_ResetDevice(), USBH_ResetPortWorker(), USBH_StartHubFdoDevice(), USBH_SyncGetDeviceHandle(), USBH_SyncGetHubCount(), USBH_SyncGetRootHubPdo(), USBH_SyncResetPort(), USBH_SyncSubmitUrb(), USBHUB_FdoStartDevice(), USBHUB_GetBusInterface(), USBHUB_GetBusInterfaceUSBDI(), USBPORT_CreateDevice(), USBPORT_FdoPnP(), USBPORT_HandleSelectConfiguration(), USBPORT_HandleSelectInterface(), USBPORT_InitializeDevice(), USBPORT_IsCompanionController(), USBPORT_QueryCapabilities(), USBPORT_QueryPciBusInterface(), USBPORT_RemoveDevice(), USBPORT_RestoreDevice(), USBPORT_SendSetupPacket(), USBPORT_SynchronizeRootHubCallback(), USBPORT_WorkerThread(), USBSTOR_GetBusInterface(), USBSTOR_QueueWaitForPendingRequests(), USBSTOR_SendIrp(), USBSTOR_SyncForwardIrp(), USBSTOR_SyncUrbRequest(), VcdRead(), VfatBlockDeviceIoControl(), VfatDiskShutDown(), VfatFlushVolume(), VfatPostRead(), VfatReadDisk(), VfatReadDiskPartial(), VfatReadFileData(), VfatWriteDisk(), VfatWriteDiskPartial(), VfatWriteFileData(), VfdDeleteDevice(), VfdDeviceThread(), VideoPortWaitForSingleObject(), vol_ioctl_passthrough(), vol_read(), vol_write(), Wait(), wait_for_flush(), WaitForControllerInterrupt(), WaitForEventThread(), WaitForOnlinesToComplete(), WaitForRemoteDatabaseSemaphore(), WaitForWork(), WorkerThread(), write_data_complete(), write_data_phys(), write_superblocks(), xHalExamineMBR(), xHalGetPartialGeometry(), xHalIoReadPartitionTable(), xHalIoSetPartitionInformation(), xHalIoWritePartitionTable(), and xHalQueryDriveLayout().

◆ KiAcquireFastMutex()

VOID FASTCALL KiAcquireFastMutex ( IN PFAST_MUTEX  FastMutex)

Definition at line 107 of file wait.c.

108 {
109  /* Increase contention count */
110  FastMutex->Contention++;
111 
112  /* Wait for the event */
113  KeWaitForSingleObject(&FastMutex->Event,
114  WrMutex,
115  KernelMode,
116  FALSE,
117  NULL);
118 }
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
smooth NULL
Definition: ftsmooth.c:416

Referenced by _ExAcquireFastMutex(), and _ExAcquireFastMutexUnsafe().

◆ KiAcquireGuardedMutex()

VOID FASTCALL KiAcquireGuardedMutex ( IN OUT PKGUARDED_MUTEX  GuardedMutex)

Definition at line 122 of file wait.c.

123 {
124  ULONG BitsToRemove, BitsToAdd;
125  LONG OldValue, NewValue;
126 
127  /* We depend on these bits being just right */
129 
130  /* Increase the contention count */
131  GuardedMutex->Contention++;
132 
133  /* Start by unlocking the Guarded Mutex */
134  BitsToRemove = GM_LOCK_BIT;
135  BitsToAdd = GM_LOCK_WAITER_INC;
136 
137  /* Start change loop */
138  for (;;)
139  {
140  /* Loop sanity checks */
141  ASSERT((BitsToRemove == GM_LOCK_BIT) ||
142  (BitsToRemove == (GM_LOCK_BIT | GM_LOCK_WAITER_WOKEN)));
143  ASSERT((BitsToAdd == GM_LOCK_WAITER_INC) ||
144  (BitsToAdd == GM_LOCK_WAITER_WOKEN));
145 
146  /* Get the Count Bits */
147  OldValue = GuardedMutex->Count;
148 
149  /* Start internal bit change loop */
150  for (;;)
151  {
152  /* Check if the Guarded Mutex is locked */
153  if (OldValue & GM_LOCK_BIT)
154  {
155  /* Sanity check */
156  ASSERT((BitsToRemove == GM_LOCK_BIT) ||
157  ((OldValue & GM_LOCK_WAITER_WOKEN) != 0));
158 
159  /* Unlock it by removing the Lock Bit */
160  NewValue = OldValue ^ BitsToRemove;
161  NewValue = InterlockedCompareExchange(&GuardedMutex->Count,
162  NewValue,
163  OldValue);
164  if (NewValue == OldValue) return;
165  }
166  else
167  {
168  /* The Guarded Mutex isn't locked, so simply set the bits */
169  NewValue = OldValue + BitsToAdd;
170  NewValue = InterlockedCompareExchange(&GuardedMutex->Count,
171  NewValue,
172  OldValue);
173  if (NewValue == OldValue) break;
174  }
175 
176  /* Old value changed, loop again */
177  OldValue = NewValue;
178  }
179 
180  /* Now we have to wait for it */
181  KeWaitForGate(&GuardedMutex->Gate, WrGuardedMutex, KernelMode);
182  ASSERT((GuardedMutex->Count & GM_LOCK_WAITER_WOKEN) != 0);
183 
184  /* Ok, the wait is done, so set the new bits */
185  BitsToRemove = GM_LOCK_BIT | GM_LOCK_WAITER_WOKEN;
186  BitsToAdd = GM_LOCK_WAITER_WOKEN;
187  }
188 }
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define GM_LOCK_BIT
long LONG
Definition: pedump.c:60
#define GM_LOCK_WAITER_INC
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define C_ASSERT(e)
Definition: ntstrsafe.h:22
VOID FASTCALL KeWaitForGate(PKGATE Gate, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode)
unsigned int ULONG
Definition: retypes.h:1
#define GM_LOCK_WAITER_WOKEN

Referenced by _KeAcquireGuardedMutex(), and _KeAcquireGuardedMutexUnsafe().

◆ KiExitDispatcher()

VOID FASTCALL KiExitDispatcher ( IN KIRQL  OldIrql)

Definition at line 199 of file wait.c.

200 {
201  PKPRCB Prcb = KeGetCurrentPrcb();
202  PKTHREAD Thread, NextThread;
203  BOOLEAN PendingApc;
204 
205  /* Make sure we're at synchronization level */
207 
208  /* Check if we have deferred threads */
210 
211  /* Check if we were called at dispatcher level or higher */
212  if (OldIrql >= DISPATCH_LEVEL)
213  {
214  /* Check if we have a thread to schedule, and that no DPC is active */
215  if ((Prcb->NextThread) && !(Prcb->DpcRoutineActive))
216  {
217  /* Request DPC interrupt */
219  }
220 
221  /* Lower IRQL and exit */
222  goto Quickie;
223  }
224 
225  /* Make sure there's a new thread scheduled */
226  if (!Prcb->NextThread) goto Quickie;
227 
228  /* Lock the PRCB */
229  KiAcquirePrcbLock(Prcb);
230 
231  /* Get the next and current threads now */
232  NextThread = Prcb->NextThread;
233  Thread = Prcb->CurrentThread;
234 
235  /* Set current thread's swap busy to true */
237 
238  /* Switch threads in PRCB */
239  Prcb->NextThread = NULL;
240  Prcb->CurrentThread = NextThread;
241 
242  /* Set thread to running */
243  NextThread->State = Running;
244 
245  /* Queue it on the ready lists */
246  KxQueueReadyThread(Thread, Prcb);
247 
248  /* Set wait IRQL */
249  Thread->WaitIrql = OldIrql;
250 
251  /* Swap threads and check if APCs were pending */
252  PendingApc = KiSwapContext(OldIrql, Thread);
253  if (PendingApc)
254  {
255  /* Lower only to APC */
257 
258  /* Deliver APCs */
261  }
262 
263  /* Lower IRQl back */
264 Quickie:
266 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
FORCEINLINE VOID KiCheckDeferredReadyList(IN PKPRCB Prcb)
Definition: ke_x.h:262
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
struct _KTHREAD * NextThread
Definition: ketypes.h:567
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
FORCEINLINE VOID KxQueueReadyThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: ke_x.h:1343
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
unsigned char BOOLEAN
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
smooth NULL
Definition: ftsmooth.c:416
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
UCHAR DpcRoutineActive
Definition: ketypes.h:688
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
volatile UCHAR State
Definition: ketypes.h:1679
VOID NTAPI KiDeliverApc(IN KPROCESSOR_MODE DeliveryMode, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: apc.c:302
#define APC_LEVEL
Definition: env_spec_w32.h:695

◆ KiUnlinkThread()

VOID FASTCALL KiUnlinkThread ( IN PKTHREAD  Thread,
IN LONG_PTR  WaitStatus 
)

Definition at line 55 of file wait.c.

57 {
58  PKWAIT_BLOCK WaitBlock;
59  PKTIMER Timer;
60 
61  /* Update wait status */
62  Thread->WaitStatus |= WaitStatus;
63 
64  /* Remove the Wait Blocks from the list */
65  WaitBlock = Thread->WaitBlockList;
66  do
67  {
68  /* Remove it */
69  RemoveEntryList(&WaitBlock->WaitListEntry);
70 
71  /* Go to the next one */
72  WaitBlock = WaitBlock->NextWaitBlock;
73  } while (WaitBlock != Thread->WaitBlockList);
74 
75  /* Remove the thread from the wait list! */
76  if (Thread->WaitListEntry.Flink) RemoveEntryList(&Thread->WaitListEntry);
77 
78  /* Check if there's a Thread Timer */
79  Timer = &Thread->Timer;
80  if (Timer->Header.Inserted) KxRemoveTreeTimer(Timer);
81 
82  /* Increment the Queue's active threads */
83  if (Thread->Queue) Thread->Queue->CurrentCount++;
84 }
LIST_ENTRY WaitListEntry
Definition: ketypes.h:444
FORCEINLINE VOID KxRemoveTreeTimer(IN PKTIMER Timer)
Definition: ke_x.h:995
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
UINT Timer
Definition: capclock.c:11

Referenced by KeSetEventBoostPriority(), and KiUnwaitThread().

◆ KiUnwaitThread()

VOID FASTCALL KiUnwaitThread ( IN PKTHREAD  Thread,
IN LONG_PTR  WaitStatus,
IN KPRIORITY  Increment 
)

Definition at line 89 of file wait.c.

92 {
93  /* Unlink the thread */
94  KiUnlinkThread(Thread, WaitStatus);
95 
96  /* Tell the scheduler do to the increment when it readies the thread */
97  ASSERT(Increment >= 0);
98  Thread->AdjustIncrement = (SCHAR)Increment;
99  Thread->AdjustReason = AdjustUnwait;
100 
101  /* Reschedule the Thread */
103 }
VOID FASTCALL KiUnlinkThread(IN PKTHREAD Thread, IN LONG_PTR WaitStatus)
Definition: wait.c:55
VOID NTAPI KiReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:429
signed char SCHAR
Definition: sqltypes.h:14
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:42

Referenced by KeAlertResumeThread(), KeAlertThread(), KiActivateWaiterQueue(), KiInsertQueueApc(), KiWaitTest(), KxUnwaitThread(), and KxUnwaitThreadForEvent().

◆ KiWaitTest()

VOID FASTCALL KiWaitTest ( IN PVOID  ObjectPointer,
IN KPRIORITY  Increment 
)

Definition at line 20 of file wait.c.

22 {
23  PLIST_ENTRY WaitEntry, WaitList;
24  PKWAIT_BLOCK WaitBlock;
25  PKTHREAD WaitThread;
26  PKMUTANT FirstObject = ObjectPointer;
27  NTSTATUS WaitStatus;
28 
29  /* Loop the Wait Entries */
30  WaitList = &FirstObject->Header.WaitListHead;
31  WaitEntry = WaitList->Flink;
32  while ((FirstObject->Header.SignalState > 0) && (WaitEntry != WaitList))
33  {
34  /* Get the current wait block */
35  WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
36  WaitThread = WaitBlock->Thread;
37  WaitStatus = STATUS_KERNEL_APC;
38 
39  /* Check the current Wait Mode */
40  if (WaitBlock->WaitType == WaitAny)
41  {
42  /* Easy case, satisfy only this wait */
43  WaitStatus = (NTSTATUS)WaitBlock->WaitKey;
44  KiSatisfyObjectWait(FirstObject, WaitThread);
45  }
46 
47  /* Now do the rest of the unwait */
48  KiUnwaitThread(WaitThread, WaitStatus, Increment);
49  WaitEntry = WaitList->Flink;
50  }
51 }
LONG NTSTATUS
Definition: precomp.h:26
struct _KTHREAD * Thread
Definition: ketypes.h:453
DISPATCHER_HEADER Header
Definition: ketypes.h:829
#define STATUS_KERNEL_APC
Definition: ntstatus.h:79
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
UCHAR WaitType
Definition: ketypes.h:446
USHORT WaitKey
Definition: ketypes.h:448
#define NTSTATUS
Definition: precomp.h:20
Definition: typedefs.h:117
#define KiSatisfyObjectWait(Object, Thread)
Definition: ke_x.h:759
LIST_ENTRY WaitListHead
Definition: ketypes.h:796
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:42
VOID FASTCALL KiUnwaitThread(IN PKTHREAD Thread, IN LONG_PTR WaitStatus, IN KPRIORITY Increment)
Definition: wait.c:89

◆ NtDelayExecution()

NTSTATUS NTAPI NtDelayExecution ( IN BOOLEAN  Alertable,
IN PLARGE_INTEGER  DelayInterval 
)

Definition at line 879 of file wait.c.

881 {
883  LARGE_INTEGER SafeInterval;
885 
886  /* Check the previous mode */
887  if (PreviousMode != KernelMode)
888  {
889  /* Enter SEH for probing */
890  _SEH2_TRY
891  {
892  /* Probe and capture the time out */
893  SafeInterval = ProbeForReadLargeInteger(DelayInterval);
894  DelayInterval = &SafeInterval;
895  }
897  {
898  /* Return the exception code */
900  }
901  _SEH2_END;
902  }
903 
904  /* Call the Kernel Function */
906  Alertable,
907  DelayInterval);
908 
909  /* Return Status */
910  return Status;
911 }
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:452
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:2982
_SEH2_TRY
Definition: create.c:4250
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4424
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12

Referenced by CsrApiRequestThread(), NtProcessStartup(), RtlpInitializeThreadPool(), RtlpIoWorkerThreadProc(), RtlpStartWorkerThread(), SleepEx(), SmpApiLoop(), and SmpLoadSubSystemsForMuSession().