3 /* GLOBAL VARIABLES *********************************************************/
5 extern TIME_ZONE_INFORMATION ExpTimeZoneInfo
;
6 extern LARGE_INTEGER ExpTimeZoneBias
;
7 extern ULONG ExpTimeZoneId
;
8 extern ULONG ExpTickCountMultiplier
;
9 extern ULONG ExpLastTimeZoneBias
;
10 extern POBJECT_TYPE ExEventPairObjectType
;
11 extern POBJECT_TYPE _ExEventObjectType
, _ExSemaphoreObjectType
;
12 extern FAST_MUTEX ExpEnvironmentLock
;
13 extern ERESOURCE ExpFirmwareTableResource
;
14 extern LIST_ENTRY ExpFirmwareTableProviderListHead
;
15 extern BOOLEAN ExpIsWinPEMode
;
16 extern LIST_ENTRY ExpSystemResourcesList
;
17 extern ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
18 extern ULONG ExpUnicodeCaseTableDataOffset
;
19 extern PVOID ExpNlsSectionPointer
;
20 extern ULONG NtGlobalFlag
;
21 extern UNICODE_STRING NtSystemRoot
;
22 extern ULONG ExpInitializationPhase
;
23 extern ULONG ExpAltTimeZoneBias
;
24 extern LIST_ENTRY ExSystemLookasideListHead
;
25 extern PCALLBACK_OBJECT PowerStateCallback
;
26 extern LIST_ENTRY ExPoolLookasideListHead
;
27 extern LIST_ENTRY ExpNonPagedLookasideListHead
;
28 extern LIST_ENTRY ExpPagedLookasideListHead
;
29 extern KSPIN_LOCK ExpNonPagedLookasideListLock
;
30 extern KSPIN_LOCK ExpPagedLookasideListLock
;
33 * NT/Cm Version Info variables
35 extern ULONG NtMajorVersion
;
36 extern ULONG NtMinorVersion
;
37 extern ULONG NtBuildNumber
;
38 extern ULONG CmNtSpBuildNumber
;
39 extern ULONG CmNtCSDVersion
;
40 extern ULONG CmNtCSDReleaseType
;
41 extern UNICODE_STRING CmVersionString
;
42 extern UNICODE_STRING CmCSDVersionString
;
43 extern CHAR NtBuildLab
[];
47 * WinDBG Debugger Worker State Machine data (see dbgctrl.c)
49 typedef enum _WINKD_WORKER_STATE
53 WinKdWorkerInitialized
56 extern WORK_QUEUE_ITEM ExpDebuggerWorkItem
;
57 extern WINKD_WORKER_STATE ExpDebuggerWork
;
58 extern PEPROCESS ExpDebuggerProcessAttach
;
59 extern PEPROCESS ExpDebuggerProcessKill
;
60 extern ULONG_PTR ExpDebuggerPageIn
;
61 VOID NTAPI
ExpDebuggerWorker(IN PVOID Context
);
62 // #endif /* _WINKD_ */
65 #define HANDLE_LOW_BITS (PAGE_SHIFT - 4)
66 #define HANDLE_HIGH_BITS (PAGE_SHIFT - 3)
68 #define HANDLE_LOW_BITS (PAGE_SHIFT - 3)
69 #define HANDLE_HIGH_BITS (PAGE_SHIFT - 2)
71 #define HANDLE_TAG_BITS (2)
72 #define HANDLE_INDEX_BITS (HANDLE_LOW_BITS + 2*HANDLE_HIGH_BITS)
73 #define KERNEL_FLAG_BITS (sizeof(PVOID)*8 - HANDLE_INDEX_BITS - HANDLE_TAG_BITS)
75 typedef union _EXHANDLE
79 ULONG_PTR TagBits
: HANDLE_TAG_BITS
;
80 ULONG_PTR Index
: HANDLE_INDEX_BITS
;
81 ULONG_PTR KernelFlag
: KERNEL_FLAG_BITS
;
85 ULONG_PTR TagBits2
: HANDLE_TAG_BITS
;
86 ULONG_PTR LowIndex
: HANDLE_LOW_BITS
;
87 ULONG_PTR MidIndex
: HANDLE_HIGH_BITS
;
88 ULONG_PTR HighIndex
: HANDLE_HIGH_BITS
;
89 ULONG_PTR KernelFlag2
: KERNEL_FLAG_BITS
;
91 HANDLE GenericHandleOverlay
;
94 } EXHANDLE
, *PEXHANDLE
;
96 typedef struct _ETIMER
101 LIST_ENTRY ActiveTimerListEntry
;
104 BOOLEAN ApcAssociated
;
106 LIST_ENTRY WakeTimerListEntry
;
111 PCALLBACK_OBJECT
*CallbackObject
;
115 typedef struct _HARDERROR_USER_PARAMETERS
117 ULONG_PTR Parameters
[MAXIMUM_HARDERROR_PARAMETERS
];
118 UNICODE_STRING Strings
[MAXIMUM_HARDERROR_PARAMETERS
];
119 WCHAR Buffer
[ANYSIZE_ARRAY
];
120 } HARDERROR_USER_PARAMETERS
, *PHARDERROR_USER_PARAMETERS
;
122 #define MAX_FAST_REFS 7
124 #define ExAcquireRundownProtection _ExAcquireRundownProtection
125 #define ExReleaseRundownProtection _ExReleaseRundownProtection
126 #define ExInitializeRundownProtection _ExInitializeRundownProtection
127 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
128 #define ExRundownCompleted _ExRundownCompleted
129 #define ExGetPreviousMode KeGetPreviousMode
133 // Various bits tagged on the handle or handle table
135 #define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1
136 #define FREE_HANDLE_MASK -1
139 // Number of entries in each table level
141 #define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
142 #define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
143 #define HIGH_LEVEL_ENTRIES (16777216 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
146 // Maximum index in each table level before we need another table
148 #define MAX_LOW_INDEX LOW_LEVEL_ENTRIES
149 #define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
150 #define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
152 #define ExpChangeRundown(x, y, z) (ULONG_PTR)InterlockedCompareExchangePointer(&x->Ptr, (PVOID)y, (PVOID)z)
153 #define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
154 #define ExpSetRundown(x, y) InterlockedExchangePointer(&x->Ptr, (PVOID)y)
159 IN PSYSTEM_POOLTAG_INFORMATION SystemInformation
,
160 IN ULONG SystemInformationLength
,
161 IN OUT PULONG ReturnLength OPTIONAL
164 /* INITIALIZATION FUNCTIONS *************************************************/
176 Phase1Initialization(
182 ExpInitializePushLocks(VOID
);
186 ExRefreshTimeZoneInformation(
187 IN PLARGE_INTEGER SystemBootTime
192 ExpInitializeWorkerThreads(VOID
);
196 ExSwapinWorkerThreads(IN BOOLEAN AllowSwap
);
200 ExpInitLookasideLists(VOID
);
204 ExInitializeSystemLookasideList(
205 IN PGENERAL_LOOKASIDE List
,
209 IN USHORT MaximumDepth
,
210 IN PLIST_ENTRY ListHead
215 ExpInitializeCallbacks(VOID
);
223 ExpInitializeExecutive(
225 IN PLOADER_PARAMETER_BLOCK LoaderBlock
230 ExpInitializeEventImplementation(VOID
);
234 ExpInitializeKeyedEventImplementation(VOID
);
238 ExpInitializeEventPairImplementation(VOID
);
242 ExpInitializeSemaphoreImplementation(VOID
);
246 ExpInitializeMutantImplementation(VOID
);
250 ExpInitializeTimerImplementation(VOID
);
254 ExpInitializeProfileImplementation(VOID
);
258 ExpResourceInitialization(VOID
);
262 ExInitPoolLookasidePointers(VOID
);
264 /* Callback Functions ********************************************************/
268 ExInitializeCallBack(
269 IN OUT PEX_CALLBACK Callback
272 PEX_CALLBACK_ROUTINE_BLOCK
275 IN PEX_CALLBACK_FUNCTION Function
,
282 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
287 ExCompareExchangeCallBack (
288 IN OUT PEX_CALLBACK CallBack
,
289 IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock
,
290 IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
293 PEX_CALLBACK_ROUTINE_BLOCK
295 ExReferenceCallBackBlock(
296 IN OUT PEX_CALLBACK CallBack
301 ExDereferenceCallBackBlock(
302 IN OUT PEX_CALLBACK CallBack
,
303 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
306 PEX_CALLBACK_FUNCTION
308 ExGetCallBackBlockRoutine(
309 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
314 ExGetCallBackBlockContext(
315 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
321 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
324 /* Rundown Functions ********************************************************/
328 ExfInitializeRundownProtection(
329 OUT PEX_RUNDOWN_REF RunRef
334 ExfReInitializeRundownProtection(
335 OUT PEX_RUNDOWN_REF RunRef
340 ExfAcquireRundownProtection(
341 IN OUT PEX_RUNDOWN_REF RunRef
346 ExfAcquireRundownProtectionEx(
347 IN OUT PEX_RUNDOWN_REF RunRef
,
353 ExfReleaseRundownProtection(
354 IN OUT PEX_RUNDOWN_REF RunRef
359 ExfReleaseRundownProtectionEx(
360 IN OUT PEX_RUNDOWN_REF RunRef
,
367 OUT PEX_RUNDOWN_REF RunRef
372 ExfWaitForRundownProtectionRelease(
373 IN OUT PEX_RUNDOWN_REF RunRef
376 /* HANDLE TABLE FUNCTIONS ***************************************************/
379 (NTAPI
*PEX_SWEEP_HANDLE_CALLBACK
)(
380 PHANDLE_TABLE_ENTRY HandleTableEntry
,
386 (NTAPI
*PEX_DUPLICATE_HANDLE_CALLBACK
)(
387 IN PEPROCESS Process
,
388 IN PHANDLE_TABLE HandleTable
,
389 IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
390 IN PHANDLE_TABLE_ENTRY NewEntry
394 (NTAPI
*PEX_CHANGE_HANDLE_CALLBACK
)(
395 PHANDLE_TABLE_ENTRY HandleTableEntry
,
401 ExpInitializeHandleTables(
408 IN PEPROCESS Process OPTIONAL
413 ExUnlockHandleTableEntry(
414 IN PHANDLE_TABLE HandleTable
,
415 IN PHANDLE_TABLE_ENTRY HandleTableEntry
421 IN PHANDLE_TABLE HandleTable
,
422 IN PHANDLE_TABLE_ENTRY HandleTableEntry
427 ExDestroyHandleTable(
428 IN PHANDLE_TABLE HandleTable
,
429 IN PVOID DestroyHandleProcedure OPTIONAL
435 IN PHANDLE_TABLE HandleTable
,
437 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
442 ExMapHandleToPointer(
443 IN PHANDLE_TABLE HandleTable
,
450 IN PEPROCESS Process
,
451 IN PHANDLE_TABLE HandleTable
,
452 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure
,
459 IN PHANDLE_TABLE HandleTable
,
461 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine
,
468 IN PHANDLE_TABLE HandleTable
,
469 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure
,
475 ExpLookupHandleTableEntry(
476 IN PHANDLE_TABLE HandleTable
,
482 ExpLockHandleTableEntry(
483 IN PHANDLE_TABLE HandleTable
,
484 IN PHANDLE_TABLE_ENTRY HandleTableEntry
487 /* PSEH EXCEPTION HANDLING **************************************************/
491 ExSystemExceptionFilter(VOID
);
493 /* CALLBACKS *****************************************************************/
497 ExDoCallBack(IN OUT PEX_CALLBACK Callback
,
502 PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock
;
503 PEX_CALLBACK_FUNCTION Function
;
505 /* Reference the block */
506 CallbackBlock
= ExReferenceCallBackBlock(Callback
);
509 /* Get the function */
510 Function
= ExGetCallBackBlockRoutine(CallbackBlock
);
512 /* Do the callback */
513 Function(Context
, Argument1
, Argument2
);
515 /* Now dereference it */
516 ExDereferenceCallBackBlock(Callback
, CallbackBlock
);
520 /* FAST REFS ******************************************************************/
524 ExGetObjectFastReference(IN EX_FAST_REF FastRef
)
526 /* Return the unbiased pointer */
527 return (PVOID
)(FastRef
.Value
& ~MAX_FAST_REFS
);
532 ExGetCountFastReference(IN EX_FAST_REF FastRef
)
534 /* Return the reference count */
535 return (ULONG
)FastRef
.RefCnt
;
540 ExInitializeFastReference(OUT PEX_FAST_REF FastRef
,
541 IN OPTIONAL PVOID Object
)
544 ASSERT((((ULONG_PTR
)Object
) & MAX_FAST_REFS
) == 0);
546 /* Check if an object is being set */
549 /* Clear the field */
550 FastRef
->Object
= NULL
;
554 /* Otherwise, we assume the object was referenced and is ready */
555 FastRef
->Value
= (ULONG_PTR
)Object
| MAX_FAST_REFS
;
561 ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef
)
563 EX_FAST_REF OldValue
, NewValue
;
565 /* Start reference loop */
568 /* Get the current reference count */
572 /* Increase the reference count */
573 NewValue
.Value
= OldValue
.Value
- 1;
574 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
577 if (NewValue
.Object
!= OldValue
.Object
) continue;
584 /* Return the old value */
590 ExInsertFastReference(IN OUT PEX_FAST_REF FastRef
,
593 EX_FAST_REF OldValue
, NewValue
;
596 ASSERT(!(((ULONG_PTR
)Object
) & MAX_FAST_REFS
));
598 /* Start update loop */
601 /* Get the current reference count */
604 /* Check if the current count is too high or if the pointer changed */
605 if (((OldValue
.RefCnt
+ MAX_FAST_REFS
) > MAX_FAST_REFS
) ||
606 ((OldValue
.Value
&~ MAX_FAST_REFS
) != (ULONG_PTR
)Object
))
612 /* Update the reference count */
613 NewValue
.Value
= OldValue
.Value
+ MAX_FAST_REFS
;
614 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
617 if (NewValue
.Object
!= OldValue
.Object
) continue;
629 ExReleaseFastReference(IN PEX_FAST_REF FastRef
,
632 EX_FAST_REF OldValue
, NewValue
;
635 ASSERT(Object
!= NULL
);
636 ASSERT(!(((ULONG_PTR
)Object
) & MAX_FAST_REFS
));
638 /* Start reference loop */
641 /* Get the current reference count */
644 /* Check if we're full if if the pointer changed */
645 if ((OldValue
.Value
^ (ULONG_PTR
)Object
) >= MAX_FAST_REFS
) return FALSE
;
647 /* Decrease the reference count */
648 NewValue
.Value
= OldValue
.Value
+ 1;
649 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
652 if (NewValue
.Object
!= OldValue
.Object
) continue;
664 ExSwapFastReference(IN PEX_FAST_REF FastRef
,
667 EX_FAST_REF NewValue
, OldValue
;
670 ASSERT((((ULONG_PTR
)Object
) & MAX_FAST_REFS
) == 0);
672 /* Check if an object is being set */
675 /* Clear the field */
676 NewValue
.Object
= NULL
;
680 /* Otherwise, we assume the object was referenced and is ready */
681 NewValue
.Value
= (ULONG_PTR
)Object
| MAX_FAST_REFS
;
684 /* Update the object */
685 OldValue
.Object
= InterlockedExchangePointer(&FastRef
->Object
, NewValue
.Object
);
691 ExCompareSwapFastReference(IN PEX_FAST_REF FastRef
,
695 EX_FAST_REF OldValue
, NewValue
;
697 /* Sanity check and start swap loop */
698 ASSERT(!(((ULONG_PTR
)Object
) & MAX_FAST_REFS
));
701 /* Get the current value */
704 /* Make sure there's enough references to swap */
705 if (!((OldValue
.Value
^ (ULONG_PTR
)OldObject
) <= MAX_FAST_REFS
)) break;
707 /* Check if we have an object to swap */
710 /* Set up the value with maximum fast references */
711 NewValue
.Value
= (ULONG_PTR
)Object
| MAX_FAST_REFS
;
715 /* Write the object address itself (which is empty) */
716 NewValue
.Value
= (ULONG_PTR
)Object
;
719 /* Do the actual compare exchange */
720 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
723 if (NewValue
.Object
!= OldValue
.Object
) continue;
729 /* Return the old value */
733 /* RUNDOWN *******************************************************************/
736 * @name ExfAcquireRundownProtection
739 * The ExfAcquireRundownProtection routine acquires rundown protection for
740 * the specified descriptor.
743 * Pointer to a rundown reference descriptor.
745 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
747 * @remarks This is the internal macro for system use only.In case the rundown
748 * was active, then the slow-path will be called through the exported
754 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
756 ULONG_PTR Value
, NewValue
;
758 /* Get the current value and mask the active bit */
759 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
761 /* Add a reference */
762 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
764 /* Change the value */
765 NewValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
766 if (NewValue
!= Value
)
768 /* Rundown was active, use long path */
769 return ExfAcquireRundownProtection(RunRef
);
777 * @name ExReleaseRundownProtection
780 * The ExReleaseRundownProtection routine releases rundown protection for
781 * the specified descriptor.
784 * Pointer to a rundown reference descriptor.
786 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
788 * @remarks This is the internal macro for system use only.In case the rundown
789 * was active, then the slow-path will be called through the exported
795 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
797 ULONG_PTR Value
, NewValue
;
799 /* Get the current value and mask the active bit */
800 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
802 /* Remove a reference */
803 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
805 /* Change the value */
806 NewValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
808 /* Check if the rundown was active */
809 if (NewValue
!= Value
)
811 /* Rundown was active, use long path */
812 ExfReleaseRundownProtection(RunRef
);
817 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
822 * @name ExInitializeRundownProtection
825 * The ExInitializeRundownProtection routine initializes a rundown
826 * protection descriptor.
829 * Pointer to a rundown reference descriptor.
833 * @remarks This is the internal macro for system use only.
838 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
840 /* Set the count to zero */
845 * @name ExWaitForRundownProtectionRelease
848 * The ExWaitForRundownProtectionRelease routine waits until the specified
849 * rundown descriptor has been released.
852 * Pointer to a rundown reference descriptor.
856 * @remarks This is the internal macro for system use only. If a wait is actually
857 * necessary, then the slow path is taken through the exported function.
862 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
866 /* Set the active bit */
867 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
868 if ((Value
) && (Value
!= EX_RUNDOWN_ACTIVE
))
870 /* If the the rundown wasn't already active, then take the long path */
871 ExfWaitForRundownProtectionRelease(RunRef
);
876 * @name ExRundownCompleted
879 * The ExRundownCompleted routine completes the rundown of the specified
880 * descriptor by setting the active bit.
883 * Pointer to a rundown reference descriptor.
887 * @remarks This is the internal macro for system use only.
892 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
895 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
897 /* Mark the counter as active */
898 ExpSetRundown(RunRef
, EX_RUNDOWN_ACTIVE
);
901 /* PUSHLOCKS *****************************************************************/
903 /* FIXME: VERIFY THESE! */
908 IN PEX_PUSH_LOCK PushLock
,
915 IN PEX_PUSH_LOCK PushLock
,
916 IN PVOID CurrentWaitBlock
921 ExWaitForUnblockPushLock(
922 IN PEX_PUSH_LOCK PushLock
,
927 * @name _ExInitializePushLock
930 * The _ExInitializePushLock macro initializes a PushLock.
933 * Pointer to the pushlock which is to be initialized.
942 _ExInitializePushLock(OUT PEX_PUSH_LOCK PushLock
)
944 /* Set the value to 0 */
947 #define ExInitializePushLock _ExInitializePushLock
950 * @name ExAcquirePushLockExclusive
953 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
956 * Pointer to the pushlock which is to be acquired.
960 * @remarks The function attempts the quickest route to acquire the lock, which is
961 * to simply set the lock bit.
962 * However, if the pushlock is already shared, the slower path is taken.
964 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
965 * This macro should usually be paired up with KeAcquireCriticalRegion.
970 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
972 /* Try acquiring the lock */
973 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
975 /* Someone changed it, use the slow path */
976 ExfAcquirePushLockExclusive(PushLock
);
980 ASSERT(PushLock
->Locked
);
984 * @name ExTryToAcquirePushLockExclusive
987 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
990 * Pointer to the pushlock which is to be acquired.
994 * @remarks The function attempts the quickest route to acquire the lock, which is
995 * to simply set the lock bit.
996 * However, if the pushlock is already shared, the slower path is taken.
998 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
999 * This macro should usually be paired up with KeAcquireCriticalRegion.
1004 ExTryToAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
1006 /* Try acquiring the lock */
1007 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
1014 ASSERT (PushLock
->Locked
);
1019 * @name ExAcquirePushLockShared
1022 * The ExAcquirePushLockShared macro acquires a shared PushLock.
1025 * Pointer to the pushlock which is to be acquired.
1029 * @remarks The function attempts the quickest route to acquire the lock, which is
1030 * to simply set the lock bit and set the share count to one.
1031 * However, if the pushlock is already shared, the slower path is taken.
1033 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
1034 * This macro should usually be paired up with KeAcquireCriticalRegion.
1039 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
1041 EX_PUSH_LOCK NewValue
;
1043 /* Try acquiring the lock */
1044 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
1045 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
1047 /* Someone changed it, use the slow path */
1048 ExfAcquirePushLockShared(PushLock
);
1052 ASSERT(PushLock
->Locked
);
1056 * @name ExConvertPushLockSharedToExclusive
1059 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
1060 * pushlock to a shared pushlock.
1063 * Pointer to the pushlock which is to be converted.
1065 * @return FALSE if conversion failed, TRUE otherwise.
1067 * @remarks The function attempts the quickest route to convert the lock, which is
1068 * to simply set the lock bit and remove any other bits.
1073 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock
)
1075 EX_PUSH_LOCK OldValue
;
1077 /* Set the expected old value */
1078 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
1080 /* Try converting the lock */
1081 if (ExpChangePushlock(PushLock
, EX_PUSH_LOCK_LOCK
, OldValue
.Value
) !=
1084 /* Conversion failed */
1089 ASSERT(PushLock
->Locked
);
1094 * @name ExWaitOnPushLock
1097 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
1100 * Pointer to a pushlock.
1104 * @remarks The function attempts to get any exclusive waiters out of their slow
1105 * path by forcing an instant acquire/release operation.
1107 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
1112 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
1114 /* Check if we're locked */
1115 if (PushLock
->Locked
)
1117 /* Acquire the lock */
1118 ExfAcquirePushLockExclusive(PushLock
);
1119 ASSERT(PushLock
->Locked
);
1122 ExfReleasePushLockExclusive(PushLock
);
1127 * @name ExReleasePushLockShared
1130 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
1133 * Pointer to a previously acquired pushlock.
1137 * @remarks The function attempts the quickest route to release the lock, which is
1138 * to simply decrease the share count and remove the lock bit.
1139 * However, if the pushlock is being waited on then the long path is taken.
1141 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
1142 * This macro should usually be paired up with KeLeaveCriticalRegion.
1147 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
1149 EX_PUSH_LOCK OldValue
;
1152 ASSERT(PushLock
->Locked
);
1154 /* Try to clear the pushlock */
1155 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
1156 if (ExpChangePushlock(PushLock
, 0, OldValue
.Ptr
) != OldValue
.Ptr
)
1158 /* There are still other people waiting on it */
1159 ExfReleasePushLockShared(PushLock
);
1164 * @name ExReleasePushLockExclusive
1167 * The ExReleasePushLockExclusive macro releases a previously
1168 * exclusively acquired PushLock.
1171 * Pointer to a previously acquired pushlock.
1175 * @remarks The function attempts the quickest route to release the lock, which is
1176 * to simply clear the locked bit.
1177 * However, if the pushlock is being waited on, the slow path is taken
1178 * in an attempt to wake up the lock.
1180 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
1181 * This macro should usually be paired up with KeLeaveCriticalRegion.
1186 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
1188 EX_PUSH_LOCK OldValue
;
1191 ASSERT(PushLock
->Locked
);
1193 /* Unlock the pushlock */
1194 OldValue
.Value
= InterlockedExchangeAddSizeT((PSIZE_T
)PushLock
,
1195 -(SSIZE_T
)EX_PUSH_LOCK_LOCK
);
1198 ASSERT(OldValue
.Locked
);
1199 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
1201 /* Check if anyone is waiting on it and it's not already waking*/
1202 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
1205 ExfTryToWakePushLock(PushLock
);
1210 * @name ExReleasePushLock
1213 * The ExReleasePushLock macro releases a previously acquired PushLock.
1216 * Pointer to a previously acquired pushlock.
1220 * @remarks The function attempts the quickest route to release the lock, which is
1221 * to simply clear all the fields and decrease the share count if required.
1222 * However, if the pushlock is being waited on then the long path is taken.
1224 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
1225 * This macro should usually be paired up with KeLeaveCriticalRegion.
1230 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
1232 EX_PUSH_LOCK OldValue
= *PushLock
;
1233 EX_PUSH_LOCK NewValue
;
1236 ASSERT(OldValue
.Locked
);
1238 /* Check if the pushlock is shared */
1239 if (OldValue
.Shared
> 1)
1241 /* Decrease the share count */
1242 NewValue
.Value
= OldValue
.Value
- EX_PUSH_LOCK_SHARE_INC
;
1246 /* Clear the pushlock entirely */
1250 /* Check if nobody is waiting on us and try clearing the lock here */
1251 if ((OldValue
.Waiting
) ||
1252 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) !=
1255 /* We have waiters, use the long path */
1256 ExfReleasePushLock(PushLock
);
1260 /* FAST MUTEX INLINES *********************************************************/
1264 _ExAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex
)
1266 PKTHREAD Thread
= KeGetCurrentThread();
1269 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
1270 (Thread
->CombinedApcDisable
!= 0) ||
1271 (Thread
->Teb
== NULL
) ||
1272 (Thread
->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
1273 ASSERT(FastMutex
->Owner
!= Thread
);
1275 /* Decrease the count */
1276 if (InterlockedDecrement(&FastMutex
->Count
))
1278 /* Someone is still holding it, use slow path */
1279 KiAcquireFastMutex(FastMutex
);
1283 FastMutex
->Owner
= Thread
;
1288 _ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex
)
1290 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
1291 (KeGetCurrentThread()->CombinedApcDisable
!= 0) ||
1292 (KeGetCurrentThread()->Teb
== NULL
) ||
1293 (KeGetCurrentThread()->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
1294 ASSERT(FastMutex
->Owner
== KeGetCurrentThread());
1296 /* Erase the owner */
1297 FastMutex
->Owner
= NULL
;
1299 /* Increase the count */
1300 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
1302 /* Someone was waiting for it, signal the waiter */
1303 KeSetEventBoostPriority(&FastMutex
->Event
, NULL
);
1309 _ExAcquireFastMutex(IN PFAST_MUTEX FastMutex
)
1312 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
1314 /* Raise IRQL to APC */
1315 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1317 /* Decrease the count */
1318 if (InterlockedDecrement(&FastMutex
->Count
))
1320 /* Someone is still holding it, use slow path */
1321 KiAcquireFastMutex(FastMutex
);
1324 /* Set the owner and IRQL */
1325 FastMutex
->Owner
= KeGetCurrentThread();
1326 FastMutex
->OldIrql
= OldIrql
;
1331 _ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex
)
1334 ASSERT(KeGetCurrentIrql() == APC_LEVEL
);
1336 /* Erase the owner */
1337 FastMutex
->Owner
= NULL
;
1338 OldIrql
= (KIRQL
)FastMutex
->OldIrql
;
1340 /* Increase the count */
1341 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
1343 /* Someone was waiting for it, signal the waiter */
1344 KeSetEventBoostPriority(&FastMutex
->Event
, NULL
);
1347 /* Lower IRQL back */
1348 KeLowerIrql(OldIrql
);
1353 _ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex
)
1356 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
1358 /* Raise to APC_LEVEL */
1359 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1361 /* Check if we can quickly acquire it */
1362 if (InterlockedCompareExchange(&FastMutex
->Count
, 0, 1) == 1)
1364 /* We have, set us as owners */
1365 FastMutex
->Owner
= KeGetCurrentThread();
1366 FastMutex
->OldIrql
= OldIrql
;
1371 /* Acquire attempt failed */
1372 KeLowerIrql(OldIrql
);
1380 _ExEnterCriticalRegionAndAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex
)
1382 /* Enter the Critical Region */
1383 KeEnterCriticalRegion();
1385 /* Acquire the mutex unsafely */
1386 _ExAcquireFastMutexUnsafe(FastMutex
);
1391 _ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(IN OUT PFAST_MUTEX FastMutex
)
1393 /* Release the mutex unsafely */
1394 _ExReleaseFastMutexUnsafe(FastMutex
);
1396 /* Leave the critical region */
1397 KeLeaveCriticalRegion();
1400 /* OTHER FUNCTIONS **********************************************************/
1404 ExTryToAcquireResourceExclusiveLite(
1405 IN PERESOURCE Resource
1409 ExpSetTimeZoneInformation(
1410 IN PTIME_ZONE_INFORMATION TimeZoneInformation
1415 ExAcquireTimeRefreshLock(
1421 ExReleaseTimeRefreshLock(
1427 ExUpdateSystemTimeFromCmos(
1428 IN BOOLEAN UpdateInterruptTime
,
1429 IN ULONG MaxSepInSeconds
1434 ExAllocateLocallyUniqueId(
1435 OUT LUID
*LocallyUniqueId
1447 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1453 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1456 #define InterlockedDecrementUL(Addend) \
1457 (ULONG)InterlockedDecrement((PLONG)(Addend))
1459 #define InterlockedIncrementUL(Addend) \
1460 (ULONG)InterlockedIncrement((PLONG)(Addend))
1462 #define InterlockedExchangeUL(Target, Value) \
1463 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
1465 #define InterlockedExchangeAddUL(Addend, Value) \
1466 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
1468 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
1469 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
1471 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
1472 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))