ReactOS 0.4.17-dev-1218-gfae4549
ke_x.h
Go to the documentation of this file.
1/*
2* PROJECT: ReactOS Kernel
3* LICENSE: GPL - See COPYING in the top level directory
4* FILE: ntoskrnl/include/internal/ke_x.h
5* PURPOSE: Internal Inlined Functions for the Kernel
6* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7*/
8
9#ifdef __cplusplus
10extern "C"
11{
12#endif
13
14#ifndef _M_ARM
18{
19 /* Return the current mode */
20 return KeGetCurrentThread()->PreviousMode;
21}
22#endif
23
24//
25// Enters a Guarded Region
26//
27#define KeEnterGuardedRegionThread(_Thread) \
28{ \
29 /* Sanity checks */ \
30 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); \
31 ASSERT((_Thread) == KeGetCurrentThread()); \
32 ASSERT(((_Thread)->SpecialApcDisable <= 0) && \
33 ((_Thread)->SpecialApcDisable != -32768)); \
34 \
35 /* Disable Special APCs */ \
36 (_Thread)->SpecialApcDisable--; \
37}
38
39#define KeEnterGuardedRegion() \
40{ \
41 PKTHREAD _Thread = KeGetCurrentThread(); \
42 KeEnterGuardedRegionThread(_Thread); \
43}
44
45//
46// Leaves a Guarded Region
47//
48#define KeLeaveGuardedRegionThread(_Thread) \
49{ \
50 /* Sanity checks */ \
51 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); \
52 ASSERT((_Thread) == KeGetCurrentThread()); \
53 ASSERT((_Thread)->SpecialApcDisable < 0); \
54 \
55 /* Leave region and check if APCs are OK now */ \
56 if (!(++(_Thread)->SpecialApcDisable)) \
57 { \
58 /* Check for Kernel APCs on the list */ \
59 if (!IsListEmpty(&(_Thread)->ApcState. \
60 ApcListHead[KernelMode])) \
61 { \
62 /* Check for APC Delivery */ \
63 KiCheckForKernelApcDelivery(); \
64 } \
65 } \
66}
67
68#define KeLeaveGuardedRegion() \
69{ \
70 PKTHREAD _Thread = KeGetCurrentThread(); \
71 KeLeaveGuardedRegionThread(_Thread); \
72}
73
74//
75// Enters a Critical Region
76//
77#define KeEnterCriticalRegionThread(_Thread) \
78{ \
79 /* Sanity checks */ \
80 ASSERT((_Thread) == KeGetCurrentThread()); \
81 ASSERT(((_Thread)->KernelApcDisable <= 0) && \
82 ((_Thread)->KernelApcDisable != -32768)); \
83 \
84 /* Disable Kernel APCs */ \
85 (_Thread)->KernelApcDisable--; \
86}
87
88#define KeEnterCriticalRegion() \
89{ \
90 PKTHREAD _Thread = KeGetCurrentThread(); \
91 KeEnterCriticalRegionThread(_Thread); \
92}
93
94//
95// Leaves a Critical Region
96//
97#define KeLeaveCriticalRegionThread(_Thread) \
98{ \
99 /* Sanity checks */ \
100 ASSERT((_Thread) == KeGetCurrentThread()); \
101 ASSERT((_Thread)->KernelApcDisable < 0); \
102 \
103 /* Enable Kernel APCs */ \
104 (_Thread)->KernelApcDisable++; \
105 \
106 /* Check if Kernel APCs are now enabled */ \
107 if (!((_Thread)->KernelApcDisable)) \
108 { \
109 /* Check if we need to request an APC Delivery */ \
110 if (!(IsListEmpty(&(_Thread)->ApcState.ApcListHead[KernelMode])) && \
111 !((_Thread)->SpecialApcDisable)) \
112 { \
113 /* Check for the right environment */ \
114 KiCheckForKernelApcDelivery(); \
115 } \
116 } \
117}
118
119#define KeLeaveCriticalRegion() \
120{ \
121 PKTHREAD _Thread = KeGetCurrentThread(); \
122 KeLeaveCriticalRegionThread(_Thread); \
123}
124
125#ifndef CONFIG_SMP
126
127//
128// This routine protects against multiple CPU acquires, it's meaningless on UP.
129//
131VOID
133{
135}
136
137//
138// This routine protects against multiple CPU acquires, it's meaningless on UP.
139//
141VOID
143{
145}
146
148KIRQL
150{
151 /* Raise to synch level */
152 return KfRaiseIrql(SYNCH_LEVEL);
153}
154
156VOID
158{
159 /* Just exit the dispatcher */
161}
162
164VOID
166{
167 /* This is a no-op at SYNCH_LEVEL for UP systems */
169 return;
170}
171
173VOID
175{
176 /* This is a no-op at SYNCH_LEVEL for UP systems */
177 return;
178}
179
180//
181// This routine makes the thread deferred ready on the boot CPU.
182//
184VOID
186{
187 /* Set the thread to deferred state and boot CPU */
188 Thread->State = DeferredReady;
189 Thread->DeferredProcessor = 0;
190
191 /* Make the thread ready immediately */
193}
194
196VOID
198 IN ULONG Cpu)
199{
200 /* This is meaningless on UP systems */
201 UNREFERENCED_PARAMETER(NewThread);
203}
204
205//
206// This routine protects against multiple CPU acquires, it's meaningless on UP.
207//
209VOID
211{
213}
214
215//
216// This routine protects against multiple CPU acquires, it's meaningless on UP.
217//
219VOID
221{
223}
224
225//
226// This routine protects against multiple CPU acquires, it's meaningless on UP.
227//
229VOID
231{
233}
234
235//
236// This routine protects against multiple CPU acquires, it's meaningless on UP.
237//
239VOID
241{
243}
244
245//
246// This routine protects against multiple CPU acquires, it's meaningless on UP.
247//
249VOID
251{
253}
254
255//
256// This routine protects against multiple CPU acquires, it's meaningless on UP.
257//
261{
263 return TRUE;
264}
265
267VOID
269{
270 /* There are no deferred ready lists on UP systems */
272}
273
275VOID
278{
279 /* We deliver instantly on UP */
280 UNREFERENCED_PARAMETER(NeedApc);
282}
283
287{
289
290 /* Nothing to do on UP */
292 return NULL;
293}
294
296VOID
298{
300
301 /* Nothing to do on UP */
302 UNREFERENCED_PARAMETER(LockQueue);
303}
304
305#else
306
308VOID
310{
311 LONG OldValue;
312
313 /* Make sure we're at a safe level to touch the lock */
315
316 /* Start acquire loop */
317 do
318 {
319 /* Loop until the other CPU releases it */
320 while (TRUE)
321 {
322 /* Check if it got released */
323 OldValue = Object->Lock;
324 if ((OldValue & KOBJECT_LOCK_BIT) == 0) break;
325
326 /* Let the CPU know that this is a loop */
328 }
329
330 /* Try acquiring the lock now */
331 } while (InterlockedCompareExchange(&Object->Lock,
332 OldValue | KOBJECT_LOCK_BIT,
333 OldValue) != OldValue);
334}
335
337VOID
339{
340 /* Make sure we're at a safe level to touch the lock */
342
343 /* Release it */
345}
346
348KIRQL
350{
351 /* Raise to synchronization level and acquire the dispatcher lock */
353}
354
356VOID
358{
359 /* First release the lock */
360 KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->
361 LockQueue[LockQueueDispatcherLock]);
362
363 /* Then exit the dispatcher */
365}
366
368VOID
370{
371 /* Acquire the dispatcher lock */
373 KeAcquireQueuedSpinLockAtDpcLevel(&KeGetCurrentPrcb()->
374 LockQueue[LockQueueDispatcherLock]);
375}
376
378VOID
380{
381 /* Release the dispatcher lock */
382 KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->
383 LockQueue[LockQueueDispatcherLock]);
384}
385
386//
387// This routine inserts a thread into the deferred ready list of the current CPU
388//
390VOID
392{
393 PKPRCB Prcb = KeGetCurrentPrcb();
394
395 /* Set the thread to deferred state and CPU */
396 Thread->State = DeferredReady;
397 Thread->DeferredProcessor = Prcb->Number;
398
399 /* Add it on the list */
400 PushEntryList(&Prcb->DeferredReadyListHead, &Thread->SwapListEntry);
401}
402
404VOID
406 IN ULONG Cpu)
407{
408 /* Check if a new thread needs to be scheduled on a different CPU */
409 if ((NewThread) && !(KeGetCurrentPrcb()->Number == Cpu))
410 {
411 /* Send an IPI to request delivery */
413 }
414}
415
416//
417// This routine sets the current thread in a swap busy state, which ensure that
418// nobody else tries to swap it concurrently.
419//
421VOID
423{
424 /* Make sure nobody already set it */
425 ASSERT(Thread->SwapBusy == FALSE);
426
427 /* Set it ourselves */
428 Thread->SwapBusy = TRUE;
429}
430
431//
432// This routine acquires the PRCB lock so that only one caller can touch
433// volatile PRCB data.
434//
435// Since this is a simple optimized spin-lock, it must only be acquired
436// at dispatcher level or higher!
437//
439VOID
441{
442 /* Make sure we're at a safe level to touch the PRCB lock */
444
445 /* Start acquire loop */
446 for (;;)
447 {
448 /* Acquire the lock and break out if we acquired it first */
449 if (!InterlockedExchange((PLONG)&Prcb->PrcbLock, 1)) break;
450
451 /* Loop until the other CPU releases it */
452 do
453 {
454 /* Let the CPU know that this is a loop */
456 } while (Prcb->PrcbLock);
457 }
458}
459
460//
461// This routine releases the PRCB lock so that other callers can touch
462// volatile PRCB data.
463//
464// Since this is a simple optimized spin-lock, it must be be only acquired
465// at dispatcher level or higher!
466//
468VOID
470{
471 /* Make sure we are above dispatch and the lock is acquired! */
473 ASSERT(Prcb->PrcbLock != 0);
474
475 /* Release it */
476 InterlockedAnd((PLONG)&Prcb->PrcbLock, 0);
477}
478
479//
480// This routine acquires the thread lock so that only one caller can touch
481// volatile thread data.
482//
483// Since this is a simple optimized spin-lock, it must be be only acquired
484// at dispatcher level or higher!
485//
487VOID
489{
490 /* Make sure we're at a safe level to touch the thread lock */
492
493 /* Start acquire loop */
494 KxAcquireSpinLock(&Thread->ThreadLock);
495}
496
497//
498// This routine releases the thread lock so that other callers can touch
499// volatile thread data.
500//
501// Since this is a simple optimized spin-lock, it must be be only acquired
502// at dispatcher level or higher!
503//
505VOID
507{
508 /* Make sure we are still above dispatch */
510
511 /* Release it */
512 KxReleaseSpinLock(&Thread->ThreadLock);
513}
514
518{
520}
521
523VOID
525{
526 /* Scan the deferred ready lists if required */
527 if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
528}
529
531VOID
534{
535 /* Check if we need to request APC delivery */
536 if (NeedApc)
537 {
538 /* Check if it's on another CPU */
540 {
541 /* Send an IPI to request delivery */
543 }
544 else
545 {
546 /* Request a software interrupt */
548 }
549 }
550}
551
555{
556 PKSPIN_LOCK_QUEUE LockQueue;
557 ULONG LockIndex;
559
560 /* Get the lock index */
561 LockIndex = Hand >> LOCK_QUEUE_TIMER_LOCK_SHIFT;
562 LockIndex &= (LOCK_QUEUE_TIMER_TABLE_LOCKS - 1);
563
564 /* Now get the lock */
565 LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueueTimerTableLock + LockIndex];
566
567 /* Acquire it and return */
568 KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
569 return LockQueue;
570}
571
573VOID
575{
577
578 /* Release the lock */
579 KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
580}
581
582#endif
583
585VOID
588{
589 /* Acquire the lock and raise to synchronization level */
591}
592
594VOID
597{
598 /* Acquire the lock */
601}
602
604VOID
607{
608 /* Acquire the lock */
610}
611
613VOID
615{
616 /* Release the lock */
618}
619
621VOID
623{
624 /* Release the lock */
626}
627
629VOID
632{
633 /* Acquire the lock and raise to synchronization level */
635}
636
638VOID
640{
641 /* Release the lock and restore previous IRQL */
643}
644
646VOID
648{
649 /* Release the lock without lowering IRQL */
651}
652
654VOID
656 IN PKLOCK_QUEUE_HANDLE DeviceLock)
657{
658 /* Check if we were called from a threaded DPC */
659 if (KeGetCurrentPrcb()->DpcThreadActive)
660 {
661 /* Lock the Queue, we're not at DPC level */
662 KeAcquireInStackQueuedSpinLock(&DeviceQueue->Lock, DeviceLock);
663 }
664 else
665 {
666 /* We must be at DPC level, acquire the lock safely */
669 DeviceLock);
670 }
671}
672
674VOID
676{
677 /* Check if we were called from a threaded DPC */
678 if (KeGetCurrentPrcb()->DpcThreadActive)
679 {
680 /* Unlock the Queue, we're not at DPC level */
682 }
683 else
684 {
685 /* We must be at DPC level, release the lock safely */
688 }
689}
690
691//
692// Satisfies the wait of a mutant dispatcher object
693//
694#define KiSatisfyMutantWait(Object, Thread) \
695{ \
696 /* Decrease the Signal State */ \
697 (Object)->Header.SignalState--; \
698 \
699 /* Check if it's now non-signaled */ \
700 if (!(Object)->Header.SignalState) \
701 { \
702 /* Set the Owner Thread */ \
703 (Object)->OwnerThread = Thread; \
704 \
705 /* Disable APCs if needed */ \
706 Thread->KernelApcDisable = Thread->KernelApcDisable - \
707 (Object)->ApcDisable; \
708 \
709 /* Check if it's abandoned */ \
710 if ((Object)->Abandoned) \
711 { \
712 /* Unabandon it */ \
713 (Object)->Abandoned = FALSE; \
714 \
715 /* Return Status */ \
716 Thread->WaitStatus = STATUS_ABANDONED; \
717 } \
718 \
719 /* Insert it into the Mutant List */ \
720 InsertHeadList(Thread->MutantListHead.Blink, \
721 &(Object)->MutantListEntry); \
722 } \
723}
724
725//
726// Satisfies the wait of any nonmutant dispatcher object
727//
728#define KiSatisfyNonMutantWait(Object) \
729{ \
730 if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
731 EventSynchronizationObject) \
732 { \
733 /* Synchronization Timers and Events just get un-signaled */ \
734 (Object)->Header.SignalState = 0; \
735 } \
736 else if ((Object)->Header.Type == SemaphoreObject) \
737 { \
738 /* These ones can have multiple states, so we only decrease it */ \
739 (Object)->Header.SignalState--; \
740 } \
741}
742
743//
744// Satisfies the wait of any dispatcher object
745//
746#define KiSatisfyObjectWait(Object, Thread) \
747{ \
748 /* Special case for Mutants */ \
749 if ((Object)->Header.Type == MutantObject) \
750 { \
751 KiSatisfyMutantWait((Object), (Thread)); \
752 } \
753 else \
754 { \
755 KiSatisfyNonMutantWait(Object); \
756 } \
757}
758
759//
760// Recalculates the due time
761//
766 IN OUT PLARGE_INTEGER NewDueTime)
767{
768 /* Don't do anything for absolute waits */
769 if (OriginalDueTime->QuadPart >= 0) return OriginalDueTime;
770
771 /* Otherwise, query the interrupt time and recalculate */
772 NewDueTime->QuadPart = KeQueryInterruptTime();
773 NewDueTime->QuadPart -= DueTime->QuadPart;
774 return NewDueTime;
775}
776
777//
778// Determines whether a thread should be added to the wait list
779//
783 IN KPROCESSOR_MODE WaitMode)
784{
785 /* Check the required conditions */
786 if ((WaitMode != KernelMode) &&
787 (Thread->EnableStackSwap) &&
788 (Thread->Priority >= (LOW_REALTIME_PRIORITY + 9)))
789 {
790 /* We are go for swap */
791 return TRUE;
792 }
793 else
794 {
795 /* Don't swap the thread */
796 return FALSE;
797 }
798}
799
800//
801// Adds a thread to the wait list
802//
803#define KiAddThreadToWaitList(Thread, Swappable) \
804{ \
805 /* Make sure it's swappable */ \
806 if (Swappable) \
807 { \
808 /* Insert it into the PRCB's List */ \
809 InsertTailList(&KeGetCurrentPrcb()->WaitListHead, \
810 &Thread->WaitListEntry); \
811 } \
812}
813
814//
815// Checks if a wait in progress should be interrupted by APCs or an alertable
816// state.
817//
822 IN KPROCESSOR_MODE WaitMode)
823{
824 /* Check if the wait is alertable */
825 if (Alertable)
826 {
827 /* It is, first check if the thread is alerted in this mode */
828 if (Thread->Alerted[WaitMode])
829 {
830 /* It is, so bail out of the wait */
831 Thread->Alerted[WaitMode] = FALSE;
832 return STATUS_ALERTED;
833 }
834 else if ((WaitMode != KernelMode) &&
835 (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
836 {
837 /* It's isn't, but this is a user wait with queued user APCs */
838 Thread->ApcState.UserApcPending = TRUE;
839 return STATUS_USER_APC;
840 }
841 else if (Thread->Alerted[KernelMode])
842 {
843 /* It isn't that either, but we're alered in kernel mode */
844 Thread->Alerted[KernelMode] = FALSE;
845 return STATUS_ALERTED;
846 }
847 }
848 else if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending))
849 {
850 /* Not alertable, but this is a user wait with pending user APCs */
851 return STATUS_USER_APC;
852 }
853
854 /* Otherwise, we're fine */
855 return STATUS_WAIT_0;
856}
857
859ULONG
861{
863}
864
865//
866// Called from KiCompleteTimer, KiInsertTreeTimer, KeSetSystemTime
867// to remove timer entries
868// See Windows HPI blog for more information.
870VOID
872{
873 ULONG Hand;
875
876 /* Remove the timer from the timer list and check if it's empty */
877 Hand = Timer->Header.Hand;
878 if (RemoveEntryList(&Timer->TimerListEntry))
879 {
880 /* Get the respective timer table entry */
882 if (&TableEntry->Entry == TableEntry->Entry.Flink)
883 {
884 /* Set the entry to an infinite absolute time */
885 TableEntry->Time.HighPart = 0xFFFFFFFF;
886 }
887 }
888
889 /* Clear the list entries on dbg builds so we can tell the timer is gone */
890#if DBG
891 Timer->TimerListEntry.Flink = NULL;
892 Timer->TimerListEntry.Blink = NULL;
893#endif
894}
895
896//
897// Called by Wait and Queue code to insert a timer for dispatching.
898// Also called by KeSetTimerEx to insert a timer from the caller.
899//
901VOID
903 IN ULONG Hand)
904{
905 PKSPIN_LOCK_QUEUE LockQueue;
907
908 /* Acquire the lock and release the dispatcher lock */
909 LockQueue = KiAcquireTimerLock(Hand);
911
912 /* Try to insert the timer */
913 if (KiInsertTimerTable(Timer, Hand))
914 {
915 /* Complete it */
916 KiCompleteTimer(Timer, LockQueue);
917 }
918 else
919 {
920 /* Do nothing, just release the lock */
921 KiReleaseTimerLock(LockQueue);
922 }
923}
924
925//
926// Called by KeSetTimerEx and KiInsertTreeTimer to calculate Due Time
927// See the Windows HPI Blog for more information
928//
933 OUT PULONG Hand)
934{
935 LARGE_INTEGER InterruptTime, SystemTime, DifferenceTime;
936
937 /* Convert to relative time if needed */
938 Timer->Header.Absolute = FALSE;
939 if (DueTime.HighPart >= 0)
940 {
941 /* Get System Time */
942 KeQuerySystemTime(&SystemTime);
943
944 /* Do the conversion */
945 DifferenceTime.QuadPart = SystemTime.QuadPart - DueTime.QuadPart;
946
947 /* Make sure it hasn't already expired */
948 Timer->Header.Absolute = TRUE;
949 if (DifferenceTime.HighPart >= 0)
950 {
951 /* Cancel everything */
952 Timer->Header.SignalState = TRUE;
953 Timer->Header.Hand = 0;
954 Timer->DueTime.QuadPart = 0;
955 *Hand = 0;
956 return FALSE;
957 }
958
959 /* Set the time as Absolute */
960 DueTime = DifferenceTime;
961 }
962
963 /* Get the Interrupt Time */
964 InterruptTime.QuadPart = KeQueryInterruptTime();
965
966 /* Recalculate due time */
967 Timer->DueTime.QuadPart = InterruptTime.QuadPart - DueTime.QuadPart;
968
969 /* Get the handle */
970 *Hand = KiComputeTimerTableIndex(Timer->DueTime.QuadPart);
971 Timer->Header.Hand = (UCHAR)*Hand;
972 Timer->Header.Inserted = TRUE;
973 return TRUE;
974}
975
976//
977// Called from Unlink and Queue Insert Code.
978// Also called by timer code when canceling an inserted timer.
979// Removes a timer from it's tree.
980//
982VOID
984{
985 ULONG Hand = Timer->Header.Hand;
986 PKSPIN_LOCK_QUEUE LockQueue;
987 PKTIMER_TABLE_ENTRY TimerEntry;
988
989 /* Acquire timer lock */
990 LockQueue = KiAcquireTimerLock(Hand);
991
992 /* Set the timer as non-inserted */
993 Timer->Header.Inserted = FALSE;
994
995 /* Remove it from the timer list */
996 if (RemoveEntryList(&Timer->TimerListEntry))
997 {
998 /* Get the entry and check if it's empty */
999 TimerEntry = &KiTimerTableListHead[Hand];
1000 if (IsListEmpty(&TimerEntry->Entry))
1001 {
1002 /* Clear the time then */
1003 TimerEntry->Time.HighPart = 0xFFFFFFFF;
1004 }
1005 }
1006
1007 /* Release the timer lock */
1008 KiReleaseTimerLock(LockQueue);
1009}
1010
1012VOID
1015 OUT PULONG Hand)
1016{
1018 LARGE_INTEGER InterruptTime, SystemTime, TimeDifference;
1019
1020 /* Check the timer's interval to see if it's absolute */
1021 Timer->Header.Absolute = FALSE;
1022 if (Interval.HighPart >= 0)
1023 {
1024 /* Get the system time and calculate the relative time */
1025 KeQuerySystemTime(&SystemTime);
1026 TimeDifference.QuadPart = SystemTime.QuadPart - Interval.QuadPart;
1027 Timer->Header.Absolute = TRUE;
1028
1029 /* Check if we've already expired */
1030 if (TimeDifference.HighPart >= 0)
1031 {
1032 /* Reset everything */
1033 Timer->DueTime.QuadPart = 0;
1034 *Hand = 0;
1035 Timer->Header.Hand = 0;
1036 return;
1037 }
1038 else
1039 {
1040 /* Update the interval */
1041 Interval = TimeDifference;
1042 }
1043 }
1044
1045 /* Calculate the due time */
1046 InterruptTime.QuadPart = KeQueryInterruptTime();
1047 DueTime = InterruptTime.QuadPart - Interval.QuadPart;
1048 Timer->DueTime.QuadPart = DueTime;
1049
1050 /* Calculate the timer handle */
1052 Timer->Header.Hand = (UCHAR)*Hand;
1053}
1054
1055#define KxDelayThreadWait() \
1056 \
1057 /* Setup the Wait Block */ \
1058 Thread->WaitBlockList = TimerBlock; \
1059 \
1060 /* Setup the timer */ \
1061 KxSetTimerForThreadWait(Timer, *Interval, &Hand); \
1062 \
1063 /* Save the due time for the caller */ \
1064 DueTime.QuadPart = Timer->DueTime.QuadPart; \
1065 \
1066 /* Link the timer to this Wait Block */ \
1067 TimerBlock->NextWaitBlock = TimerBlock; \
1068 Timer->Header.WaitListHead.Flink = &TimerBlock->WaitListEntry; \
1069 Timer->Header.WaitListHead.Blink = &TimerBlock->WaitListEntry; \
1070 \
1071 /* Clear wait status */ \
1072 Thread->WaitStatus = STATUS_SUCCESS; \
1073 \
1074 /* Setup wait fields */ \
1075 Thread->Alertable = Alertable; \
1076 Thread->WaitReason = DelayExecution; \
1077 Thread->WaitMode = WaitMode; \
1078 \
1079 /* Check if we can swap the thread's stack */ \
1080 Thread->WaitListEntry.Flink = NULL; \
1081 Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
1082 \
1083 /* Set the wait time */ \
1084 Thread->WaitTime = KeTickCount.LowPart;
1085
1086#define KxMultiThreadWait() \
1087 /* Link wait block array to the thread */ \
1088 Thread->WaitBlockList = WaitBlockArray; \
1089 \
1090 /* Reset the index */ \
1091 Index = 0; \
1092 \
1093 /* Loop wait blocks */ \
1094 do \
1095 { \
1096 /* Fill out the wait block */ \
1097 WaitBlock = &WaitBlockArray[Index]; \
1098 WaitBlock->Object = Object[Index]; \
1099 WaitBlock->WaitKey = (USHORT)Index; \
1100 WaitBlock->WaitType = WaitType; \
1101 WaitBlock->Thread = Thread; \
1102 \
1103 /* Link to next block */ \
1104 WaitBlock->NextWaitBlock = &WaitBlockArray[Index + 1]; \
1105 Index++; \
1106 } while (Index < Count); \
1107 \
1108 /* Link the last block */ \
1109 WaitBlock->NextWaitBlock = WaitBlockArray; \
1110 \
1111 /* Set default wait status */ \
1112 Thread->WaitStatus = STATUS_WAIT_0; \
1113 \
1114 /* Check if we have a timer */ \
1115 if (Timeout) \
1116 { \
1117 /* Link to the block */ \
1118 TimerBlock->NextWaitBlock = WaitBlockArray; \
1119 \
1120 /* Setup the timer */ \
1121 KxSetTimerForThreadWait(Timer, *Timeout, &Hand); \
1122 \
1123 /* Save the due time for the caller */ \
1124 DueTime.QuadPart = Timer->DueTime.QuadPart; \
1125 \
1126 /* Initialize the list */ \
1127 InitializeListHead(&Timer->Header.WaitListHead); \
1128 } \
1129 \
1130 /* Set wait settings */ \
1131 Thread->Alertable = Alertable; \
1132 Thread->WaitMode = WaitMode; \
1133 Thread->WaitReason = WaitReason; \
1134 \
1135 /* Check if we can swap the thread's stack */ \
1136 Thread->WaitListEntry.Flink = NULL; \
1137 Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
1138 \
1139 /* Set the wait time */ \
1140 Thread->WaitTime = KeTickCount.LowPart;
1141
1142#define KxSingleThreadWait() \
1143 /* Setup the Wait Block */ \
1144 Thread->WaitBlockList = WaitBlock; \
1145 WaitBlock->WaitKey = STATUS_SUCCESS; \
1146 WaitBlock->Object = Object; \
1147 WaitBlock->WaitType = WaitAny; \
1148 \
1149 /* Clear wait status */ \
1150 Thread->WaitStatus = STATUS_SUCCESS; \
1151 \
1152 /* Check if we have a timer */ \
1153 if (Timeout) \
1154 { \
1155 /* Setup the timer */ \
1156 KxSetTimerForThreadWait(Timer, *Timeout, &Hand); \
1157 \
1158 /* Save the due time for the caller */ \
1159 DueTime.QuadPart = Timer->DueTime.QuadPart; \
1160 \
1161 /* Pointer to timer block */ \
1162 WaitBlock->NextWaitBlock = TimerBlock; \
1163 TimerBlock->NextWaitBlock = WaitBlock; \
1164 \
1165 /* Link the timer to this Wait Block */ \
1166 Timer->Header.WaitListHead.Flink = &TimerBlock->WaitListEntry; \
1167 Timer->Header.WaitListHead.Blink = &TimerBlock->WaitListEntry; \
1168 } \
1169 else \
1170 { \
1171 /* No timer block, just ourselves */ \
1172 WaitBlock->NextWaitBlock = WaitBlock; \
1173 } \
1174 \
1175 /* Set wait settings */ \
1176 Thread->Alertable = Alertable; \
1177 Thread->WaitMode = WaitMode; \
1178 Thread->WaitReason = WaitReason; \
1179 \
1180 /* Check if we can swap the thread's stack */ \
1181 Thread->WaitListEntry.Flink = NULL; \
1182 Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
1183 \
1184 /* Set the wait time */ \
1185 Thread->WaitTime = KeTickCount.LowPart;
1186
1187#define KxQueueThreadWait() \
1188 /* Setup the Wait Block */ \
1189 Thread->WaitBlockList = WaitBlock; \
1190 WaitBlock->WaitKey = STATUS_SUCCESS; \
1191 WaitBlock->Object = Queue; \
1192 WaitBlock->WaitType = WaitAny; \
1193 WaitBlock->Thread = Thread; \
1194 \
1195 /* Clear wait status */ \
1196 Thread->WaitStatus = STATUS_SUCCESS; \
1197 \
1198 /* Check if we have a timer */ \
1199 if (Timeout) \
1200 { \
1201 /* Setup the timer */ \
1202 KxSetTimerForThreadWait(Timer, *Timeout, &Hand); \
1203 \
1204 /* Save the due time for the caller */ \
1205 DueTime.QuadPart = Timer->DueTime.QuadPart; \
1206 \
1207 /* Pointer to timer block */ \
1208 WaitBlock->NextWaitBlock = TimerBlock; \
1209 TimerBlock->NextWaitBlock = WaitBlock; \
1210 \
1211 /* Link the timer to this Wait Block */ \
1212 Timer->Header.WaitListHead.Flink = &TimerBlock->WaitListEntry; \
1213 Timer->Header.WaitListHead.Blink = &TimerBlock->WaitListEntry; \
1214 } \
1215 else \
1216 { \
1217 /* No timer block, just ourselves */ \
1218 WaitBlock->NextWaitBlock = WaitBlock; \
1219 } \
1220 \
1221 /* Set wait settings */ \
1222 Thread->Alertable = FALSE; \
1223 Thread->WaitMode = WaitMode; \
1224 Thread->WaitReason = WrQueue; \
1225 \
1226 /* Check if we can swap the thread's stack */ \
1227 Thread->WaitListEntry.Flink = NULL; \
1228 Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
1229 \
1230 /* Set the wait time */ \
1231 Thread->WaitTime = KeTickCount.LowPart;
1232
1233//
1234// Unwaits a Thread
1235//
1237VOID
1240{
1241 PLIST_ENTRY WaitEntry, WaitList;
1242 PKWAIT_BLOCK WaitBlock;
1243 PKTHREAD WaitThread;
1244 ULONG WaitKey;
1245
1246 /* Loop the Wait Entries */
1247 WaitList = &Object->WaitListHead;
1248 ASSERT(IsListEmpty(&Object->WaitListHead) == FALSE);
1249 WaitEntry = WaitList->Flink;
1250 do
1251 {
1252 /* Get the current wait block */
1253 WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
1254
1255 /* Get the waiting thread */
1256 WaitThread = WaitBlock->Thread;
1257
1258 /* Check the current Wait Mode */
1259 if (WaitBlock->WaitType == WaitAny)
1260 {
1261 /* Use the actual wait key */
1262 WaitKey = WaitBlock->WaitKey;
1263 }
1264 else
1265 {
1266 /* Otherwise, use STATUS_KERNEL_APC */
1267 WaitKey = STATUS_KERNEL_APC;
1268 }
1269
1270 /* Unwait the thread */
1271 KiUnwaitThread(WaitThread, WaitKey, Increment);
1272
1273 /* Next entry */
1274 WaitEntry = WaitList->Flink;
1275 } while (WaitEntry != WaitList);
1276}
1277
1278//
1279// Unwaits a Thread waiting on an event
1280//
1282VOID
1285{
1286 PLIST_ENTRY WaitEntry, WaitList;
1287 PKWAIT_BLOCK WaitBlock;
1288 PKTHREAD WaitThread;
1289
1290 /* Loop the Wait Entries */
1291 WaitList = &Event->Header.WaitListHead;
1292 ASSERT(IsListEmpty(&Event->Header.WaitListHead) == FALSE);
1293 WaitEntry = WaitList->Flink;
1294 do
1295 {
1296 /* Get the current wait block */
1297 WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
1298
1299 /* Get the waiting thread */
1300 WaitThread = WaitBlock->Thread;
1301
1302 /* Check the current Wait Mode */
1303 if (WaitBlock->WaitType == WaitAny)
1304 {
1305 /* Un-signal it */
1306 Event->Header.SignalState = 0;
1307
1308 /* Un-signal the event and unwait the thread */
1309 KiUnwaitThread(WaitThread, WaitBlock->WaitKey, Increment);
1310 break;
1311 }
1312
1313 /* Unwait the thread with STATUS_KERNEL_APC */
1315
1316 /* Next entry */
1317 WaitEntry = WaitList->Flink;
1318 } while (WaitEntry != WaitList);
1319}
1320
1321//
1322// This routine queues a thread that is ready on the PRCB's ready lists.
1323// If this thread cannot currently run on this CPU, then the thread is
1324// added to the deferred ready list instead.
1325//
1326// This routine must be entered with the PRCB lock held and it will exit
1327// with the PRCB lock released!
1328//
1330_Releases_lock_(Prcb->PrcbLock)
1332VOID
1333KxQueueReadyThread(IN PKTHREAD Thread,
1334 IN PKPRCB Prcb)
1335{
1336 BOOLEAN Preempted;
1338
1339 /* Sanity checks */
1340 ASSERT(Prcb == KeGetCurrentPrcb());
1341#ifdef CONFIG_SMP
1342 ASSERT(Prcb->PrcbLock != 0);
1343#endif
1344 ASSERT(Thread->State == Running);
1345 ASSERT(Thread->NextProcessor == Prcb->Number);
1346
1347 /* Check if this thread is allowed to run in this CPU */
1348#ifdef CONFIG_SMP
1349 if ((Thread->Affinity) & (Prcb->SetMember))
1350#else
1351 if (TRUE)
1352#endif
1353 {
1354 /* Set thread ready for execution */
1355 Thread->State = Ready;
1356
1357 /* Save current priority and if someone had pre-empted it */
1358 Priority = Thread->Priority;
1359 Preempted = Thread->Preempted;
1360
1361 /* We're not pre-empting now, and set the wait time */
1362 Thread->Preempted = FALSE;
1363 Thread->WaitTime = KeTickCount.LowPart;
1364
1365 /* Sanity check */
1366 ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
1367
1368 /* Insert this thread in the appropriate order */
1369 Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],
1370 &Thread->WaitListEntry) :
1371 InsertTailList(&Prcb->DispatcherReadyListHead[Priority],
1372 &Thread->WaitListEntry);
1373
1374 /* Update the ready summary */
1375 Prcb->ReadySummary |= PRIORITY_MASK(Priority);
1376
1377 /* Sanity check */
1378 ASSERT(Priority == Thread->Priority);
1379
1380 /* Release the PRCB lock */
1381 KiReleasePrcbLock(Prcb);
1382 }
1383 else
1384 {
1385 /* Otherwise, prepare this thread to be deferred */
1386 Thread->State = DeferredReady;
1387 Thread->DeferredProcessor = Prcb->Number;
1388
1389 /* Release the lock and defer scheduling */
1390 KiReleasePrcbLock(Prcb);
1392 }
1393}
1394
1395//
1396// This routine scans for an appropriate ready thread to select at the
1397// given priority and for the given CPU.
1398//
1402 IN PKPRCB Prcb)
1403{
1404 ULONG PrioritySet;
1405 LONG HighPriority;
1406 PLIST_ENTRY ListEntry;
1408
1409 /* Save the current mask and get the priority set for the CPU */
1410 PrioritySet = Prcb->ReadySummary >> Priority;
1411 if (!PrioritySet) goto Quickie;
1412
1413 /* Get the highest priority possible */
1414 BitScanReverse((PULONG)&HighPriority, PrioritySet);
1415 ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);
1416 HighPriority += Priority;
1417
1418 /* Make sure the list isn't empty at the highest priority */
1419 ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);
1420
1421 /* Get the first thread on the list */
1422 ListEntry = Prcb->DispatcherReadyListHead[HighPriority].Flink;
1423 Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);
1424
1425 /* Make sure this thread is here for a reason */
1426 ASSERT(HighPriority == Thread->Priority);
1427 ASSERT(Thread->Affinity & AFFINITY_MASK(Prcb->Number));
1428 ASSERT(Thread->NextProcessor == Prcb->Number);
1429
1430 /* Remove it from the list */
1431 if (RemoveEntryList(&Thread->WaitListEntry))
1432 {
1433 /* The list is empty now, reset the ready summary */
1434 Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);
1435 }
1436
1437 /* Sanity check and return the thread */
1438Quickie:
1439 ASSERT((Thread == NULL) ||
1440 (Thread->BasePriority == 0) ||
1441 (Thread->Priority != 0));
1442 return Thread;
1443}
1444
1445//
1446// This routine computes the new priority for a thread. It is only valid for
1447// threads with priorities in the dynamic priority range.
1448//
1450SCHAR
1453{
1455
1456 /* Priority sanity checks */
1457 ASSERT((Thread->PriorityDecrement >= 0) &&
1458 (Thread->PriorityDecrement <= Thread->Priority));
1459 ASSERT((Thread->Priority < LOW_REALTIME_PRIORITY) ?
1460 TRUE : (Thread->PriorityDecrement == 0));
1461
1462 /* Get the current priority */
1463 Priority = Thread->Priority;
1465 {
1466 /* Decrease priority by the priority decrement */
1467 Priority -= (Thread->PriorityDecrement + Adjustment);
1468
1469 /* Don't go out of bounds */
1470 if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;
1471
1472 /* Reset the priority decrement */
1473 Thread->PriorityDecrement = 0;
1474 }
1475
1476 /* Sanity check */
1477 ASSERT((Thread->BasePriority == 0) || (Priority != 0));
1478
1479 /* Return the new priority */
1480 return Priority;
1481}
1482
1483//
1484// Guarded Mutex Routines
1485//
1487VOID
1489{
1490 /* Setup the Initial Data */
1491 GuardedMutex->Count = GM_LOCK_BIT;
1492 GuardedMutex->Owner = NULL;
1493 GuardedMutex->Contention = 0;
1494
1495 /* Initialize the Wait Gate */
1496 KeInitializeGate(&GuardedMutex->Gate);
1497}
1498
1500VOID
1502{
1504
1505 /* Sanity checks */
1507 (Thread->SpecialApcDisable < 0) ||
1508 (Thread->Teb == NULL) ||
1509 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
1510 ASSERT(GuardedMutex->Owner != Thread);
1511
1512 /* Remove the lock */
1513 if (!InterlockedBitTestAndReset(&GuardedMutex->Count, GM_LOCK_BIT_V))
1514 {
1515 /* The Guarded Mutex was already locked, enter contented case */
1516 KiAcquireGuardedMutex(GuardedMutex);
1517 }
1518
1519 /* Set the Owner */
1520 GuardedMutex->Owner = Thread;
1521}
1522
1524VOID
1526{
1527 LONG OldValue, NewValue;
1528
1529 /* Sanity checks */
1531 (KeGetCurrentThread()->SpecialApcDisable < 0) ||
1532 (KeGetCurrentThread()->Teb == NULL) ||
1534 ASSERT(GuardedMutex->Owner == KeGetCurrentThread());
1535
1536 /* Destroy the Owner */
1537 GuardedMutex->Owner = NULL;
1538
1539 /* Add the Lock Bit */
1540 OldValue = InterlockedExchangeAdd(&GuardedMutex->Count, GM_LOCK_BIT);
1541 ASSERT((OldValue & GM_LOCK_BIT) == 0);
1542
1543 /* Check if it was already locked, but not woken */
1544 if ((OldValue) && !(OldValue & GM_LOCK_WAITER_WOKEN))
1545 {
1546 /* Update the Oldvalue to what it should be now */
1547 OldValue += GM_LOCK_BIT;
1548
1549 /* The mutex will be woken, minus one waiter */
1550 NewValue = OldValue + GM_LOCK_WAITER_WOKEN -
1552
1553 /* Remove the Woken bit */
1554 if (InterlockedCompareExchange(&GuardedMutex->Count,
1555 NewValue,
1556 OldValue) == OldValue)
1557 {
1558 /* Signal the Gate */
1559 KeSignalGateBoostPriority(&GuardedMutex->Gate);
1560 }
1561 }
1562}
1563
1565VOID
1567{
1569
1570 /* Sanity checks */
1572 ASSERT(GuardedMutex->Owner != Thread);
1573
1574 /* Disable Special APCs */
1576
1577 /* Remove the lock */
1578 if (!InterlockedBitTestAndReset(&GuardedMutex->Count, GM_LOCK_BIT_V))
1579 {
1580 /* The Guarded Mutex was already locked, enter contented case */
1581 KiAcquireGuardedMutex(GuardedMutex);
1582 }
1583
1584 /* Set the Owner and Special APC Disable state */
1585 GuardedMutex->Owner = Thread;
1586 GuardedMutex->SpecialApcDisable = Thread->SpecialApcDisable;
1587}
1588
1590VOID
1592{
1594 LONG OldValue, NewValue;
1595
1596 /* Sanity checks */
1598 ASSERT(GuardedMutex->Owner == Thread);
1599 ASSERT(Thread->SpecialApcDisable == GuardedMutex->SpecialApcDisable);
1600
1601 /* Destroy the Owner */
1602 GuardedMutex->Owner = NULL;
1603
1604 /* Add the Lock Bit */
1605 OldValue = InterlockedExchangeAdd(&GuardedMutex->Count, GM_LOCK_BIT);
1606 ASSERT((OldValue & GM_LOCK_BIT) == 0);
1607
1608 /* Check if it was already locked, but not woken */
1609 if ((OldValue) && !(OldValue & GM_LOCK_WAITER_WOKEN))
1610 {
1611 /* Update the Oldvalue to what it should be now */
1612 OldValue += GM_LOCK_BIT;
1613
1614 /* The mutex will be woken, minus one waiter */
1615 NewValue = OldValue + GM_LOCK_WAITER_WOKEN -
1617
1618 /* Remove the Woken bit */
1619 if (InterlockedCompareExchange(&GuardedMutex->Count,
1620 NewValue,
1621 OldValue) == OldValue)
1622 {
1623 /* Signal the Gate */
1624 KeSignalGateBoostPriority(&GuardedMutex->Gate);
1625 }
1626 }
1627
1628 /* Re-enable APCs */
1630}
1631
1633BOOLEAN
1635{
1637
1638 /* Block APCs */
1640
1641 /* Remove the lock */
1642 if (!InterlockedBitTestAndReset(&GuardedMutex->Count, GM_LOCK_BIT_V))
1643 {
1644 /* Re-enable APCs */
1647
1648 /* Return failure */
1649 return FALSE;
1650 }
1651
1652 /* Set the Owner and APC State */
1653 GuardedMutex->Owner = Thread;
1654 GuardedMutex->SpecialApcDisable = Thread->SpecialApcDisable;
1655 return TRUE;
1656}
1657
1658
1660VOID
1662{
1664}
1665
1667VOID
1669{
1671}
1672
1673#if defined(_M_IX86) || defined(_M_AMD64)
1675VOID
1676KiCpuId(
1677 PCPU_INFO CpuInfo,
1679{
1680 __cpuid((INT*)CpuInfo->AsUINT32, Function);
1681}
1682
1684VOID
1685KiCpuIdEx(
1686 PCPU_INFO CpuInfo,
1688 ULONG SubFunction)
1689{
1690 __cpuidex((INT*)CpuInfo->AsUINT32, Function, SubFunction);
1691}
1692#endif /* _M_IX86 || _M_AMD64 */
1693
1695ULONG64
1698{
1699 /* Hack until we switched to NTDDI_VISTA, where CycleTime is in KTHREAD */
1700 PETHREAD EThread = (PETHREAD)Thread;
1701
1702#ifdef _WIN64
1703 return EThread->CycleTime;
1704#else
1705 /* Read in a loop until we get a match */
1706 ULARGE_INTEGER CycleTimeAsULI;
1707 for (;;)
1708 {
1709 volatile ULARGE_INTEGER* CycleTimePtr = (volatile ULARGE_INTEGER*)&EThread->CycleTime;
1710 CycleTimeAsULI.HighPart = CycleTimePtr->HighPart;
1711 CycleTimeAsULI.LowPart = CycleTimePtr->LowPart;
1712 if (CycleTimeAsULI.HighPart == EThread->CycleTimeHigh)
1713 break;
1715 }
1716 return CycleTimeAsULI.QuadPart;
1717#endif
1718}
1719
1720
1722VOID
1725 _In_ ULONG64 NewCycleTime)
1726{
1727 /* Hack until we switched to NTDDI_VISTA, where CycleTime is in KTHREAD */
1728 PETHREAD EThread = (PETHREAD)Thread;
1729
1730#ifdef _WIN64
1731 EThread->CycleTime = NewCycleTime;
1732#else
1733 /* On 32 bit systems we need to use the same trick as for writing a KSYSTEM_TIME */
1734 ULARGE_INTEGER NewCycleTimeAsULI;
1735 NewCycleTimeAsULI.QuadPart = NewCycleTime;
1736 volatile ULARGE_INTEGER* CycleTimePtr = (volatile ULARGE_INTEGER*)&EThread->CycleTime;
1737 EThread->CycleTimeHigh = NewCycleTimeAsULI.HighPart;
1738 CycleTimePtr->LowPart = NewCycleTimeAsULI.LowPart;
1739 CycleTimePtr->HighPart = NewCycleTimeAsULI.HighPart;
1740#endif
1741}
1742
1743#ifdef __cplusplus
1744} // extern "C"
1745#endif
unsigned char BOOLEAN
Definition: actypes.h:127
#define MM_SYSTEM_RANGE_START
Definition: armddk.h:18
#define InterlockedExchange
Definition: armddk.h:54
LONG NTSTATUS
Definition: precomp.h:26
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
#define _Requires_lock_held_(lock)
#define _Releases_lock_(lock)
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG KPRIORITY
Definition: compat.h:803
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
ULONG Handle
Definition: gdb_input.c:15
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
KIRQL FASTCALL KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:119
VOID FASTCALL KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:142
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
#define KeGetCurrentThread
Definition: hal.h:55
_In_ UCXUSBDEVICE _In_ UCXENDPOINT _In_ ULONG Priority
Definition: hubucx.h:414
#define LOW_REALTIME_PRIORITY
#define HIGH_PRIORITY
#define BitScanReverse
Definition: interlocked.h:6
#define InterlockedExchangeAdd
Definition: interlocked.h:196
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define InterlockedBitTestAndReset
Definition: interlocked.h:35
#define InterlockedAnd
Definition: interlocked.h:77
PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType)
Definition: intrin_ppc.h:682
__INTRIN_INLINE void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
Definition: intrin_x86.h:1680
FORCEINLINE VOID _KeAcquireGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: ke_x.h:1501
FORCEINLINE VOID KiAcquireNmiListLock(OUT PKIRQL OldIrql)
Definition: ke_x.h:1661
FORCEINLINE VOID KiAcquireApcLockRaiseToSynch(IN PKTHREAD Thread, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:586
FORCEINLINE BOOLEAN KiComputeDueTime(IN PKTIMER Timer, IN LARGE_INTEGER DueTime, OUT PULONG Hand)
Definition: ke_x.h:931
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
FORCEINLINE VOID KiCheckDeferredReadyList(IN PKPRCB Prcb)
Definition: ke_x.h:268
FORCEINLINE VOID KiAcquireApcLockRaiseToDpc(IN PKTHREAD Thread, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:605
FORCEINLINE VOID _KeReleaseGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: ke_x.h:1525
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1401
#define KeEnterGuardedRegionThread(_Thread)
Definition: ke_x.h:27
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:210
FORCEINLINE VOID KxRemoveTreeTimer(IN PKTIMER Timer)
Definition: ke_x.h:983
FORCEINLINE VOID KiWriteThreadCycleTime(_Inout_ PKTHREAD Thread, _In_ ULONG64 NewCycleTime)
Definition: ke_x.h:1723
FORCEINLINE BOOLEAN KiTryToAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:260
FORCEINLINE VOID KiRemoveEntryTimer(IN PKTIMER Timer)
Definition: ke_x.h:871
FORCEINLINE VOID KiReleaseProcessLockFromSynchLevel(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:647
FORCEINLINE VOID KiReleaseTimerLock(IN PKSPIN_LOCK_QUEUE LockQueue)
Definition: ke_x.h:297
FORCEINLINE PLARGE_INTEGER KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime, IN PLARGE_INTEGER DueTime, IN OUT PLARGE_INTEGER NewDueTime)
Definition: ke_x.h:764
FORCEINLINE VOID KiRequestApcInterrupt(IN BOOLEAN NeedApc, IN UCHAR Processor)
Definition: ke_x.h:276
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:230
FORCEINLINE ULONG KiComputeTimerTableIndex(IN ULONGLONG DueTime)
Definition: ke_x.h:860
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:240
FORCEINLINE ULONG64 KiReadThreadCycleTime(_In_ PKTHREAD Thread)
Definition: ke_x.h:1696
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1238
FORCEINLINE BOOLEAN _KeTryToAcquireGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: ke_x.h:1634
FORCEINLINE VOID _KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: ke_x.h:1566
FORCEINLINE VOID KiReleaseNmiListLock(IN KIRQL OldIrql)
Definition: ke_x.h:1668
FORCEINLINE PKSPIN_LOCK_QUEUE KiAcquireTimerLock(IN ULONG Hand)
Definition: ke_x.h:286
FORCEINLINE VOID KiReleaseDispatcherObject(IN DISPATCHER_HEADER *Object)
Definition: ke_x.h:142
FORCEINLINE VOID _KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: ke_x.h:1488
FORCEINLINE VOID KiInsertDeferredReadyList(IN PKTHREAD Thread)
Definition: ke_x.h:185
FORCEINLINE VOID _KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: ke_x.h:1591
FORCEINLINE BOOLEAN KiCheckThreadStackSwap(IN PKTHREAD Thread, IN KPROCESSOR_MODE WaitMode)
Definition: ke_x.h:782
#define KeLeaveGuardedRegionThread(_Thread)
Definition: ke_x.h:48
FORCEINLINE VOID KiAcquireDispatcherObject(IN DISPATCHER_HEADER *Object)
Definition: ke_x.h:132
FORCEINLINE VOID KiReleaseDispatcherLockFromSynchLevel(VOID)
Definition: ke_x.h:174
FORCEINLINE VOID KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:639
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:250
FORCEINLINE VOID KxSetTimerForThreadWait(IN PKTIMER Timer, IN LARGE_INTEGER Interval, OUT PULONG Hand)
Definition: ke_x.h:1013
FORCEINLINE VOID KiAcquireDispatcherLockAtSynchLevel(VOID)
Definition: ke_x.h:165
FORCEINLINE VOID KiAcquireApcLockAtSynchLevel(IN PKTHREAD Thread, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:595
FORCEINLINE VOID KiRescheduleThread(IN BOOLEAN NewThread, IN ULONG Cpu)
Definition: ke_x.h:197
FORCEINLINE VOID KiReleaseApcLockFromSynchLevel(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:622
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
FORCEINLINE VOID KiAcquireDeviceQueueLock(IN PKDEVICE_QUEUE DeviceQueue, IN PKLOCK_QUEUE_HANDLE DeviceLock)
Definition: ke_x.h:655
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
FORCEINLINE VOID KiAcquireProcessLockRaiseToSynch(IN PKPROCESS Process, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:630
FORCEINLINE VOID KxInsertTimer(IN PKTIMER Timer, IN ULONG Hand)
Definition: ke_x.h:902
FORCEINLINE NTSTATUS KiCheckAlertability(IN PKTHREAD Thread, IN BOOLEAN Alertable, IN KPROCESSOR_MODE WaitMode)
Definition: ke_x.h:820
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1451
FORCEINLINE VOID KiReleaseApcLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:614
FORCEINLINE VOID KiReleaseDeviceQueueLock(IN PKLOCK_QUEUE_HANDLE DeviceLock)
Definition: ke_x.h:675
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1283
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1197
#define IPI_DPC
Definition: ketypes.h:313
#define IPI_APC
Definition: ketypes.h:312
#define KeGetPreviousMode()
Definition: ketypes.h:1115
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:453
_In_ ULONG Number
Definition: haltypes.h:1940
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
FORCEINLINE KAFFINITY AFFINITY_MASK(ULONG Index)
Definition: kefuncs.h:39
@ Ready
Definition: ketypes.h:408
@ Running
Definition: ketypes.h:409
@ DeferredReady
Definition: ketypes.h:414
#define KOBJECT_LOCK_BIT
Definition: ketypes.h:121
DWORD Interval
Definition: netstat.c:28
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ WaitAny
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
#define PRIORITY_MASK(Priority)
Definition: ke.h:163
VOID FASTCALL KiCompleteTimer(IN PKTIMER Timer, IN PKSPIN_LOCK_QUEUE LockQueue)
Definition: timerobj.c:167
VOID FASTCALL KiAcquireGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: wait.c:122
KSPIN_LOCK KiNmiCallbackListLock
Definition: bug.c:34
VOID FASTCALL KiProcessDeferredReadyList(IN PKPRCB Prcb)
Definition: thrdschd.c:41
BOOLEAN FASTCALL KiInsertTimerTable(IN PKTIMER Timer, IN ULONG Hand)
Definition: timerobj.c:63
VOID FASTCALL KiDeferredReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:150
VOID FASTCALL KiIpiSend(KAFFINITY TargetSet, ULONG IpiRequest)
VOID FASTCALL KeSignalGateBoostPriority(PKGATE Gate)
VOID FASTCALL KeInitializeGate(PKGATE Gate)
VOID FASTCALL KiUnwaitThread(IN PKTHREAD Thread, IN LONG_PTR WaitStatus, IN KPRIORITY Increment)
Definition: wait.c:89
VOID FASTCALL KiExitDispatcher(KIRQL OldIrql)
ULONG KeMaximumIncrement
Definition: clock.c:20
VOID FASTCALL KeAcquireInStackQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:363
VOID FASTCALL KeReleaseInStackQueuedSpinLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:395
BOOLEAN FASTCALL KeTryToAcquireSpinLockAtDpcLevel(IN OUT PKSPIN_LOCK SpinLock)
Definition: spinlock.c:309
#define STATUS_WAIT_0
Definition: ntstatus.h:330
#define STATUS_ALERTED
Definition: ntstatus.h:133
#define STATUS_USER_APC
Definition: ntstatus.h:130
#define STATUS_KERNEL_APC
Definition: ntstatus.h:132
long LONG
Definition: pedump.c:60
#define YieldProcessor
Definition: ke.h:48
#define KeQueryInterruptTime()
Definition: ke.h:37
signed char SCHAR
Definition: sqltypes.h:14
EX_PUSH_LOCK ThreadLock
Definition: pstypes.h:1353
USHORT Number
Definition: ketypes.h:663
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:732
ULONG LowPart
Definition: wdm.h:5
Definition: ketypes.h:918
ULARGE_INTEGER Time
Definition: ketypes.h:923
LIST_ENTRY Entry
Definition: ketypes.h:922
struct _KTHREAD * Thread
Definition: ketypes.h:533
UCHAR WaitType
Definition: ketypes.h:526
USHORT WaitKey
Definition: ketypes.h:528
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: compat.h:836
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:582
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint64_t ULONGLONG
Definition: typedefs.h:67
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
UINT32 AsUINT32[4]
Definition: ketypes.h:398
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFTIMER _In_ LONGLONG DueTime
Definition: wdftimer.h:190
#define FORCEINLINE
Definition: wdftypes.h:67
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4319
_In_ KPRIORITY _In_ LONG Adjustment
Definition: kefuncs.h:427
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_In_ UCHAR Processor
Definition: kefuncs.h:670
#define GM_LOCK_BIT_V
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define GM_LOCK_WAITER_WOKEN
#define LOCK_QUEUE_TIMER_TABLE_LOCKS
#define LOCK_QUEUE_TIMER_LOCK_SHIFT
#define TIMER_TABLE_SIZE
Definition: ketypes.h:916
@ LockQueueTimerTableLock
Definition: ketypes.h:743
@ LockQueueDispatcherLock
Definition: ketypes.h:726
#define GM_LOCK_BIT
#define GM_LOCK_WAITER_INC
FORCEINLINE VOID PushEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PSINGLE_LIST_ENTRY Entry)
Definition: rtlfuncs.h:256