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 KERNEL_FLAG_BITS (sizeof(PVOID)*8 - 31)
73 typedef union _EXHANDLE
83 ULONG_PTR LowIndex
:HANDLE_LOW_BITS
;
84 ULONG_PTR MidIndex
:HANDLE_HIGH_BITS
;
85 ULONG_PTR HighIndex
:HANDLE_HIGH_BITS
;
86 ULONG_PTR KernelFlag
:KERNEL_FLAG_BITS
;
88 HANDLE GenericHandleOverlay
;
90 } EXHANDLE
, *PEXHANDLE
;
92 typedef struct _ETIMER
97 LIST_ENTRY ActiveTimerListEntry
;
100 BOOLEAN ApcAssociated
;
102 LIST_ENTRY WakeTimerListEntry
;
107 PCALLBACK_OBJECT
*CallbackObject
;
111 typedef struct _HARDERROR_USER_PARAMETERS
113 ULONG_PTR Parameters
[MAXIMUM_HARDERROR_PARAMETERS
];
114 UNICODE_STRING Strings
[MAXIMUM_HARDERROR_PARAMETERS
];
115 WCHAR Buffer
[ANYSIZE_ARRAY
];
116 } HARDERROR_USER_PARAMETERS
, *PHARDERROR_USER_PARAMETERS
;
118 #define MAX_FAST_REFS 7
120 #define ExAcquireRundownProtection _ExAcquireRundownProtection
121 #define ExReleaseRundownProtection _ExReleaseRundownProtection
122 #define ExInitializeRundownProtection _ExInitializeRundownProtection
123 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
124 #define ExRundownCompleted _ExRundownCompleted
125 #define ExGetPreviousMode KeGetPreviousMode
129 // Various bits tagged on the handle or handle table
131 #define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1
132 #define FREE_HANDLE_MASK -1
135 // Number of entries in each table level
137 #define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
138 #define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
139 #define HIGH_LEVEL_ENTRIES (16777216 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
142 // Maximum index in each table level before we need another table
144 #define MAX_LOW_INDEX LOW_LEVEL_ENTRIES
145 #define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
146 #define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
148 #define ExpChangeRundown(x, y, z) (ULONG_PTR)InterlockedCompareExchangePointer(&x->Ptr, (PVOID)y, (PVOID)z)
149 #define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
150 #define ExpSetRundown(x, y) InterlockedExchangePointer(&x->Ptr, (PVOID)y)
155 IN PSYSTEM_POOLTAG_INFORMATION SystemInformation
,
156 IN ULONG SystemInformationLength
,
157 IN OUT PULONG ReturnLength OPTIONAL
160 /* INITIALIZATION FUNCTIONS *************************************************/
172 Phase1Initialization(
178 ExpInitializePushLocks(VOID
);
182 ExRefreshTimeZoneInformation(
183 IN PLARGE_INTEGER SystemBootTime
188 ExpInitializeWorkerThreads(VOID
);
192 ExSwapinWorkerThreads(IN BOOLEAN AllowSwap
);
196 ExpInitLookasideLists(VOID
);
200 ExInitializeSystemLookasideList(
201 IN PGENERAL_LOOKASIDE List
,
205 IN USHORT MaximumDepth
,
206 IN PLIST_ENTRY ListHead
211 ExpInitializeCallbacks(VOID
);
219 ExpInitializeExecutive(
221 IN PLOADER_PARAMETER_BLOCK LoaderBlock
226 ExpInitializeEventImplementation(VOID
);
230 ExpInitializeKeyedEventImplementation(VOID
);
234 ExpInitializeEventPairImplementation(VOID
);
238 ExpInitializeSemaphoreImplementation(VOID
);
242 ExpInitializeMutantImplementation(VOID
);
246 ExpInitializeTimerImplementation(VOID
);
250 ExpInitializeProfileImplementation(VOID
);
254 ExpResourceInitialization(VOID
);
258 ExInitPoolLookasidePointers(VOID
);
260 /* Callback Functions ********************************************************/
264 ExInitializeCallBack(
265 IN OUT PEX_CALLBACK Callback
268 PEX_CALLBACK_ROUTINE_BLOCK
271 IN PEX_CALLBACK_FUNCTION Function
,
278 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
283 ExCompareExchangeCallBack (
284 IN OUT PEX_CALLBACK CallBack
,
285 IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock
,
286 IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
289 PEX_CALLBACK_ROUTINE_BLOCK
291 ExReferenceCallBackBlock(
292 IN OUT PEX_CALLBACK CallBack
297 ExDereferenceCallBackBlock(
298 IN OUT PEX_CALLBACK CallBack
,
299 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
302 PEX_CALLBACK_FUNCTION
304 ExGetCallBackBlockRoutine(
305 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
310 ExGetCallBackBlockContext(
311 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
317 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
320 /* Rundown Functions ********************************************************/
324 ExfInitializeRundownProtection(
325 OUT PEX_RUNDOWN_REF RunRef
330 ExfReInitializeRundownProtection(
331 OUT PEX_RUNDOWN_REF RunRef
336 ExfAcquireRundownProtection(
337 IN OUT PEX_RUNDOWN_REF RunRef
342 ExfAcquireRundownProtectionEx(
343 IN OUT PEX_RUNDOWN_REF RunRef
,
349 ExfReleaseRundownProtection(
350 IN OUT PEX_RUNDOWN_REF RunRef
355 ExfReleaseRundownProtectionEx(
356 IN OUT PEX_RUNDOWN_REF RunRef
,
363 OUT PEX_RUNDOWN_REF RunRef
368 ExfWaitForRundownProtectionRelease(
369 IN OUT PEX_RUNDOWN_REF RunRef
372 /* HANDLE TABLE FUNCTIONS ***************************************************/
375 (NTAPI
*PEX_SWEEP_HANDLE_CALLBACK
)(
376 PHANDLE_TABLE_ENTRY HandleTableEntry
,
382 (NTAPI
*PEX_DUPLICATE_HANDLE_CALLBACK
)(
383 IN PEPROCESS Process
,
384 IN PHANDLE_TABLE HandleTable
,
385 IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
386 IN PHANDLE_TABLE_ENTRY NewEntry
390 (NTAPI
*PEX_CHANGE_HANDLE_CALLBACK
)(
391 PHANDLE_TABLE_ENTRY HandleTableEntry
,
397 ExpInitializeHandleTables(
404 IN PEPROCESS Process OPTIONAL
409 ExUnlockHandleTableEntry(
410 IN PHANDLE_TABLE HandleTable
,
411 IN PHANDLE_TABLE_ENTRY HandleTableEntry
417 IN PHANDLE_TABLE HandleTable
,
418 IN PHANDLE_TABLE_ENTRY HandleTableEntry
423 ExDestroyHandleTable(
424 IN PHANDLE_TABLE HandleTable
,
425 IN PVOID DestroyHandleProcedure OPTIONAL
431 IN PHANDLE_TABLE HandleTable
,
433 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
438 ExMapHandleToPointer(
439 IN PHANDLE_TABLE HandleTable
,
446 IN PEPROCESS Process
,
447 IN PHANDLE_TABLE HandleTable
,
448 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure
,
455 IN PHANDLE_TABLE HandleTable
,
457 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine
,
464 IN PHANDLE_TABLE HandleTable
,
465 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure
,
471 ExpLookupHandleTableEntry(
472 IN PHANDLE_TABLE HandleTable
,
478 ExpLockHandleTableEntry(
479 IN PHANDLE_TABLE HandleTable
,
480 IN PHANDLE_TABLE_ENTRY HandleTableEntry
483 /* PSEH EXCEPTION HANDLING **************************************************/
487 ExSystemExceptionFilter(VOID
);
489 /* CALLBACKS *****************************************************************/
493 ExDoCallBack(IN OUT PEX_CALLBACK Callback
,
498 PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock
;
499 PEX_CALLBACK_FUNCTION Function
;
501 /* Reference the block */
502 CallbackBlock
= ExReferenceCallBackBlock(Callback
);
505 /* Get the function */
506 Function
= ExGetCallBackBlockRoutine(CallbackBlock
);
508 /* Do the callback */
509 Function(Context
, Argument1
, Argument2
);
511 /* Now dereference it */
512 ExDereferenceCallBackBlock(Callback
, CallbackBlock
);
516 /* FAST REFS ******************************************************************/
520 ExGetObjectFastReference(IN EX_FAST_REF FastRef
)
522 /* Return the unbiased pointer */
523 return (PVOID
)(FastRef
.Value
& ~MAX_FAST_REFS
);
528 ExGetCountFastReference(IN EX_FAST_REF FastRef
)
530 /* Return the reference count */
531 return (ULONG
)FastRef
.RefCnt
;
536 ExInitializeFastReference(OUT PEX_FAST_REF FastRef
,
537 IN OPTIONAL PVOID Object
)
540 ASSERT((((ULONG_PTR
)Object
) & MAX_FAST_REFS
) == 0);
542 /* Check if an object is being set */
545 /* Clear the field */
546 FastRef
->Object
= NULL
;
550 /* Otherwise, we assume the object was referenced and is ready */
551 FastRef
->Value
= (ULONG_PTR
)Object
| MAX_FAST_REFS
;
557 ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef
)
559 EX_FAST_REF OldValue
, NewValue
;
561 /* Start reference loop */
564 /* Get the current reference count */
568 /* Increase the reference count */
569 NewValue
.Value
= OldValue
.Value
- 1;
570 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
573 if (NewValue
.Object
!= OldValue
.Object
) continue;
580 /* Return the old value */
586 ExInsertFastReference(IN OUT PEX_FAST_REF FastRef
,
589 EX_FAST_REF OldValue
, NewValue
;
592 ASSERT(!(((ULONG_PTR
)Object
) & MAX_FAST_REFS
));
594 /* Start update loop */
597 /* Get the current reference count */
600 /* Check if the current count is too high or if the pointer changed */
601 if (((OldValue
.RefCnt
+ MAX_FAST_REFS
) > MAX_FAST_REFS
) ||
602 ((OldValue
.Value
&~ MAX_FAST_REFS
) != (ULONG_PTR
)Object
))
608 /* Update the reference count */
609 NewValue
.Value
= OldValue
.Value
+ MAX_FAST_REFS
;
610 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
613 if (NewValue
.Object
!= OldValue
.Object
) continue;
625 ExReleaseFastReference(IN PEX_FAST_REF FastRef
,
628 EX_FAST_REF OldValue
, NewValue
;
631 ASSERT(Object
!= NULL
);
632 ASSERT(!(((ULONG_PTR
)Object
) & MAX_FAST_REFS
));
634 /* Start reference loop */
637 /* Get the current reference count */
640 /* Check if we're full if if the pointer changed */
641 if ((OldValue
.Value
^ (ULONG_PTR
)Object
) >= MAX_FAST_REFS
) return FALSE
;
643 /* Decrease the reference count */
644 NewValue
.Value
= OldValue
.Value
+ 1;
645 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
648 if (NewValue
.Object
!= OldValue
.Object
) continue;
660 ExSwapFastReference(IN PEX_FAST_REF FastRef
,
663 EX_FAST_REF NewValue
, OldValue
;
666 ASSERT((((ULONG_PTR
)Object
) & MAX_FAST_REFS
) == 0);
668 /* Check if an object is being set */
671 /* Clear the field */
672 NewValue
.Object
= NULL
;
676 /* Otherwise, we assume the object was referenced and is ready */
677 NewValue
.Value
= (ULONG_PTR
)Object
| MAX_FAST_REFS
;
680 /* Update the object */
681 OldValue
.Object
= InterlockedExchangePointer(&FastRef
->Object
, NewValue
.Object
);
687 ExCompareSwapFastReference(IN PEX_FAST_REF FastRef
,
691 EX_FAST_REF OldValue
, NewValue
;
693 /* Sanity check and start swap loop */
694 ASSERT(!(((ULONG_PTR
)Object
) & MAX_FAST_REFS
));
697 /* Get the current value */
700 /* Make sure there's enough references to swap */
701 if (!((OldValue
.Value
^ (ULONG_PTR
)OldObject
) <= MAX_FAST_REFS
)) break;
703 /* Check if we have an object to swap */
706 /* Set up the value with maximum fast references */
707 NewValue
.Value
= (ULONG_PTR
)Object
| MAX_FAST_REFS
;
711 /* Write the object address itself (which is empty) */
712 NewValue
.Value
= (ULONG_PTR
)Object
;
715 /* Do the actual compare exchange */
716 NewValue
.Object
= ExpChangePushlock(&FastRef
->Object
,
719 if (NewValue
.Object
!= OldValue
.Object
) continue;
725 /* Return the old value */
729 /* RUNDOWN *******************************************************************/
732 * @name ExfAcquireRundownProtection
735 * The ExfAcquireRundownProtection routine acquires rundown protection for
736 * the specified descriptor.
739 * Pointer to a rundown reference descriptor.
741 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
743 * @remarks This is the internal macro for system use only.In case the rundown
744 * was active, then the slow-path will be called through the exported
750 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
752 ULONG_PTR Value
, NewValue
;
754 /* Get the current value and mask the active bit */
755 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
757 /* Add a reference */
758 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
760 /* Change the value */
761 NewValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
762 if (NewValue
!= Value
)
764 /* Rundown was active, use long path */
765 return ExfAcquireRundownProtection(RunRef
);
773 * @name ExReleaseRundownProtection
776 * The ExReleaseRundownProtection routine releases rundown protection for
777 * the specified descriptor.
780 * Pointer to a rundown reference descriptor.
782 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
784 * @remarks This is the internal macro for system use only.In case the rundown
785 * was active, then the slow-path will be called through the exported
791 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
793 ULONG_PTR Value
, NewValue
;
795 /* Get the current value and mask the active bit */
796 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
798 /* Remove a reference */
799 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
801 /* Change the value */
802 NewValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
804 /* Check if the rundown was active */
805 if (NewValue
!= Value
)
807 /* Rundown was active, use long path */
808 ExfReleaseRundownProtection(RunRef
);
813 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
818 * @name ExInitializeRundownProtection
821 * The ExInitializeRundownProtection routine initializes a rundown
822 * protection descriptor.
825 * Pointer to a rundown reference descriptor.
829 * @remarks This is the internal macro for system use only.
834 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
836 /* Set the count to zero */
841 * @name ExWaitForRundownProtectionRelease
844 * The ExWaitForRundownProtectionRelease routine waits until the specified
845 * rundown descriptor has been released.
848 * Pointer to a rundown reference descriptor.
852 * @remarks This is the internal macro for system use only. If a wait is actually
853 * necessary, then the slow path is taken through the exported function.
858 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
862 /* Set the active bit */
863 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
864 if ((Value
) && (Value
!= EX_RUNDOWN_ACTIVE
))
866 /* If the the rundown wasn't already active, then take the long path */
867 ExfWaitForRundownProtectionRelease(RunRef
);
872 * @name ExRundownCompleted
875 * The ExRundownCompleted routine completes the rundown of the specified
876 * descriptor by setting the active bit.
879 * Pointer to a rundown reference descriptor.
883 * @remarks This is the internal macro for system use only.
888 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
891 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
893 /* Mark the counter as active */
894 ExpSetRundown(RunRef
, EX_RUNDOWN_ACTIVE
);
897 /* PUSHLOCKS *****************************************************************/
899 /* FIXME: VERIFY THESE! */
904 IN PEX_PUSH_LOCK PushLock
,
911 IN PEX_PUSH_LOCK PushLock
,
912 IN PVOID CurrentWaitBlock
917 ExWaitForUnblockPushLock(
918 IN PEX_PUSH_LOCK PushLock
,
923 * @name _ExInitializePushLock
926 * The _ExInitializePushLock macro initializes a PushLock.
929 * Pointer to the pushlock which is to be initialized.
938 _ExInitializePushLock(OUT PEX_PUSH_LOCK PushLock
)
940 /* Set the value to 0 */
943 #define ExInitializePushLock _ExInitializePushLock
946 * @name ExAcquirePushLockExclusive
949 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
952 * Pointer to the pushlock which is to be acquired.
956 * @remarks The function attempts the quickest route to acquire the lock, which is
957 * to simply set the lock bit.
958 * However, if the pushlock is already shared, the slower path is taken.
960 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
961 * This macro should usually be paired up with KeAcquireCriticalRegion.
966 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
968 /* Try acquiring the lock */
969 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
971 /* Someone changed it, use the slow path */
972 ExfAcquirePushLockExclusive(PushLock
);
976 ASSERT(PushLock
->Locked
);
980 * @name ExTryToAcquirePushLockExclusive
983 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
986 * Pointer to the pushlock which is to be acquired.
990 * @remarks The function attempts the quickest route to acquire the lock, which is
991 * to simply set the lock bit.
992 * However, if the pushlock is already shared, the slower path is taken.
994 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
995 * This macro should usually be paired up with KeAcquireCriticalRegion.
1000 ExTryToAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
1002 /* Try acquiring the lock */
1003 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
1010 ASSERT (PushLock
->Locked
);
1015 * @name ExAcquirePushLockShared
1018 * The ExAcquirePushLockShared macro acquires a shared PushLock.
1021 * Pointer to the pushlock which is to be acquired.
1025 * @remarks The function attempts the quickest route to acquire the lock, which is
1026 * to simply set the lock bit and set the share count to one.
1027 * However, if the pushlock is already shared, the slower path is taken.
1029 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
1030 * This macro should usually be paired up with KeAcquireCriticalRegion.
1035 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
1037 EX_PUSH_LOCK NewValue
;
1039 /* Try acquiring the lock */
1040 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
1041 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
1043 /* Someone changed it, use the slow path */
1044 ExfAcquirePushLockShared(PushLock
);
1048 ASSERT(PushLock
->Locked
);
1052 * @name ExConvertPushLockSharedToExclusive
1055 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
1056 * pushlock to a shared pushlock.
1059 * Pointer to the pushlock which is to be converted.
1061 * @return FALSE if conversion failed, TRUE otherwise.
1063 * @remarks The function attempts the quickest route to convert the lock, which is
1064 * to simply set the lock bit and remove any other bits.
1069 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock
)
1071 EX_PUSH_LOCK OldValue
;
1073 /* Set the expected old value */
1074 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
1076 /* Try converting the lock */
1077 if (ExpChangePushlock(PushLock
, EX_PUSH_LOCK_LOCK
, OldValue
.Value
) !=
1080 /* Conversion failed */
1085 ASSERT(PushLock
->Locked
);
1090 * @name ExWaitOnPushLock
1093 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
1096 * Pointer to a pushlock.
1100 * @remarks The function attempts to get any exclusive waiters out of their slow
1101 * path by forcing an instant acquire/release operation.
1103 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
1108 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
1110 /* Check if we're locked */
1111 if (PushLock
->Locked
)
1113 /* Acquire the lock */
1114 ExfAcquirePushLockExclusive(PushLock
);
1115 ASSERT(PushLock
->Locked
);
1118 ExfReleasePushLockExclusive(PushLock
);
1123 * @name ExReleasePushLockShared
1126 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
1129 * Pointer to a previously acquired pushlock.
1133 * @remarks The function attempts the quickest route to release the lock, which is
1134 * to simply decrease the share count and remove the lock bit.
1135 * However, if the pushlock is being waited on then the long path is taken.
1137 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
1138 * This macro should usually be paired up with KeLeaveCriticalRegion.
1143 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
1145 EX_PUSH_LOCK OldValue
;
1148 ASSERT(PushLock
->Locked
);
1150 /* Try to clear the pushlock */
1151 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
1152 if (ExpChangePushlock(PushLock
, 0, OldValue
.Ptr
) != OldValue
.Ptr
)
1154 /* There are still other people waiting on it */
1155 ExfReleasePushLockShared(PushLock
);
1160 * @name ExReleasePushLockExclusive
1163 * The ExReleasePushLockExclusive macro releases a previously
1164 * exclusively acquired PushLock.
1167 * Pointer to a previously acquired pushlock.
1171 * @remarks The function attempts the quickest route to release the lock, which is
1172 * to simply clear the locked bit.
1173 * However, if the pushlock is being waited on, the slow path is taken
1174 * in an attempt to wake up the lock.
1176 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
1177 * This macro should usually be paired up with KeLeaveCriticalRegion.
1182 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
1184 EX_PUSH_LOCK OldValue
;
1187 ASSERT(PushLock
->Locked
);
1189 /* Unlock the pushlock */
1190 OldValue
.Value
= InterlockedExchangeAddSizeT((PSIZE_T
)PushLock
,
1191 -(SSIZE_T
)EX_PUSH_LOCK_LOCK
);
1194 ASSERT(OldValue
.Locked
);
1195 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
1197 /* Check if anyone is waiting on it and it's not already waking*/
1198 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
1201 ExfTryToWakePushLock(PushLock
);
1206 * @name ExReleasePushLock
1209 * The ExReleasePushLock macro releases a previously acquired PushLock.
1212 * Pointer to a previously acquired pushlock.
1216 * @remarks The function attempts the quickest route to release the lock, which is
1217 * to simply clear all the fields and decrease the share count if required.
1218 * However, if the pushlock is being waited on then the long path is taken.
1220 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
1221 * This macro should usually be paired up with KeLeaveCriticalRegion.
1226 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
1228 EX_PUSH_LOCK OldValue
= *PushLock
;
1229 EX_PUSH_LOCK NewValue
;
1232 ASSERT(OldValue
.Locked
);
1234 /* Check if the pushlock is shared */
1235 if (OldValue
.Shared
> 1)
1237 /* Decrease the share count */
1238 NewValue
.Value
= OldValue
.Value
- EX_PUSH_LOCK_SHARE_INC
;
1242 /* Clear the pushlock entirely */
1246 /* Check if nobody is waiting on us and try clearing the lock here */
1247 if ((OldValue
.Waiting
) ||
1248 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) !=
1251 /* We have waiters, use the long path */
1252 ExfReleasePushLock(PushLock
);
1256 /* FAST MUTEX INLINES *********************************************************/
1260 _ExAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex
)
1262 PKTHREAD Thread
= KeGetCurrentThread();
1265 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
1266 (Thread
->CombinedApcDisable
!= 0) ||
1267 (Thread
->Teb
== NULL
) ||
1268 (Thread
->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
1269 ASSERT(FastMutex
->Owner
!= Thread
);
1271 /* Decrease the count */
1272 if (InterlockedDecrement(&FastMutex
->Count
))
1274 /* Someone is still holding it, use slow path */
1275 KiAcquireFastMutex(FastMutex
);
1279 FastMutex
->Owner
= Thread
;
1284 _ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex
)
1286 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
1287 (KeGetCurrentThread()->CombinedApcDisable
!= 0) ||
1288 (KeGetCurrentThread()->Teb
== NULL
) ||
1289 (KeGetCurrentThread()->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
1290 ASSERT(FastMutex
->Owner
== KeGetCurrentThread());
1292 /* Erase the owner */
1293 FastMutex
->Owner
= NULL
;
1295 /* Increase the count */
1296 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
1298 /* Someone was waiting for it, signal the waiter */
1299 KeSetEventBoostPriority(&FastMutex
->Event
, NULL
);
1305 _ExAcquireFastMutex(IN PFAST_MUTEX FastMutex
)
1308 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
1310 /* Raise IRQL to APC */
1311 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1313 /* Decrease the count */
1314 if (InterlockedDecrement(&FastMutex
->Count
))
1316 /* Someone is still holding it, use slow path */
1317 KiAcquireFastMutex(FastMutex
);
1320 /* Set the owner and IRQL */
1321 FastMutex
->Owner
= KeGetCurrentThread();
1322 FastMutex
->OldIrql
= OldIrql
;
1327 _ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex
)
1330 ASSERT(KeGetCurrentIrql() == APC_LEVEL
);
1332 /* Erase the owner */
1333 FastMutex
->Owner
= NULL
;
1334 OldIrql
= (KIRQL
)FastMutex
->OldIrql
;
1336 /* Increase the count */
1337 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
1339 /* Someone was waiting for it, signal the waiter */
1340 KeSetEventBoostPriority(&FastMutex
->Event
, NULL
);
1343 /* Lower IRQL back */
1344 KeLowerIrql(OldIrql
);
1349 _ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex
)
1352 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
1354 /* Raise to APC_LEVEL */
1355 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1357 /* Check if we can quickly acquire it */
1358 if (InterlockedCompareExchange(&FastMutex
->Count
, 0, 1) == 1)
1360 /* We have, set us as owners */
1361 FastMutex
->Owner
= KeGetCurrentThread();
1362 FastMutex
->OldIrql
= OldIrql
;
1367 /* Acquire attempt failed */
1368 KeLowerIrql(OldIrql
);
1376 _ExEnterCriticalRegionAndAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex
)
1378 /* Enter the Critical Region */
1379 KeEnterCriticalRegion();
1381 /* Acquire the mutex unsafely */
1382 _ExAcquireFastMutexUnsafe(FastMutex
);
1387 _ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(IN OUT PFAST_MUTEX FastMutex
)
1389 /* Release the mutex unsafely */
1390 _ExReleaseFastMutexUnsafe(FastMutex
);
1392 /* Leave the critical region */
1393 KeLeaveCriticalRegion();
1396 /* OTHER FUNCTIONS **********************************************************/
1400 ExTryToAcquireResourceExclusiveLite(
1401 IN PERESOURCE Resource
1405 ExpSetTimeZoneInformation(
1406 IN PTIME_ZONE_INFORMATION TimeZoneInformation
1411 ExAcquireTimeRefreshLock(
1417 ExReleaseTimeRefreshLock(
1423 ExUpdateSystemTimeFromCmos(
1424 IN BOOLEAN UpdateInterruptTime
,
1425 IN ULONG MaxSepInSeconds
1430 ExAllocateLocallyUniqueId(
1431 OUT LUID
*LocallyUniqueId
1443 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1449 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1452 #define InterlockedDecrementUL(Addend) \
1453 (ULONG)InterlockedDecrement((PLONG)(Addend))
1455 #define InterlockedIncrementUL(Addend) \
1456 (ULONG)InterlockedIncrement((PLONG)(Addend))
1458 #define InterlockedExchangeUL(Target, Value) \
1459 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
1461 #define InterlockedExchangeAddUL(Addend, Value) \
1462 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
1464 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
1465 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
1467 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
1468 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))