1 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H
2 #define __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H
4 /* GLOBAL VARIABLES *********************************************************/
6 extern TIME_ZONE_INFORMATION ExpTimeZoneInfo
;
7 extern LARGE_INTEGER ExpTimeZoneBias
;
8 extern ULONG ExpTimeZoneId
;
9 extern ULONG ExpTickCountMultiplier
;
10 extern ULONG ExpLastTimeZoneBias
;
11 extern POBJECT_TYPE ExEventPairObjectType
;
12 extern POBJECT_TYPE _ExEventObjectType
, _ExSemaphoreObjectType
;
13 extern ULONG NtBuildNumber
;
14 extern ULONG NtMajorVersion
;
15 extern ULONG NtMinorVersion
;
16 extern FAST_MUTEX ExpEnvironmentLock
;
17 extern ERESOURCE ExpFirmwareTableResource
;
18 extern LIST_ENTRY ExpFirmwareTableProviderListHead
;
19 extern BOOLEAN ExpIsWinPEMode
;
20 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
21 ULONG ExpUnicodeCaseTableDataOffset
;
22 PVOID ExpNlsSectionPointer
;
24 #define MAX_FAST_REFS 7
26 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
27 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
28 EX_HANDLE_ENTRY_AUDITONCLOSE)))
29 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->Object) & \
30 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
31 EX_HANDLE_ENTRY_AUDITONCLOSE)))
33 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
35 #define ExAcquireResourceLock(l, i) { \
37 Ke386DisableInterrupts(); \
39 #define ExReleaseResourceLock(l, i) Ke386EnableInterrupts();
41 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
42 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
45 #define ExAcquireRundownProtection _ExAcquireRundownProtection
46 #define ExReleaseRundownProtection _ExReleaseRundownProtection
47 #define ExInitializeRundownProtection _ExInitializeRundownProtection
48 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
49 #define ExRundownCompleted _ExRundownCompleted
50 #define ExGetPreviousMode KeGetPreviousMode
52 /* INITIALIZATION FUNCTIONS *************************************************/
70 ExpInitializePushLocks(VOID
);
74 ExRefreshTimeZoneInformation(
75 IN PLARGE_INTEGER SystemBootTime
80 ExpInitializeWorkerThreads(VOID
);
84 ExpInitLookasideLists(VOID
);
88 ExInitializeSystemLookasideList(
89 IN PGENERAL_LOOKASIDE List
,
93 IN USHORT MaximumDepth
,
94 IN PLIST_ENTRY ListHead
99 ExpInitializeCallbacks(VOID
);
107 ExpInitializeExecutive(
109 IN PLOADER_PARAMETER_BLOCK LoaderBlock
114 ExpInitializeEventImplementation(VOID
);
118 ExpInitializeEventImplementation(VOID
);
122 ExpInitializeEventPairImplementation(VOID
);
126 ExpInitializeSemaphoreImplementation(VOID
);
130 ExpInitializeMutantImplementation(VOID
);
134 ExpInitializeTimerImplementation(VOID
);
138 ExpInitializeProfileImplementation(VOID
);
142 ExpResourceInitialization(VOID
);
146 ExInitPoolLookasidePointers(VOID
);
148 /* Callback Functions ********************************************************/
152 ExInitializeCallBack(
153 IN PEX_CALLBACK Callback
156 /* Rundown Functions ********************************************************/
160 ExfInitializeRundownProtection(
161 OUT PEX_RUNDOWN_REF RunRef
166 ExfReInitializeRundownProtection(
167 OUT PEX_RUNDOWN_REF RunRef
172 ExfAcquireRundownProtection(
173 IN OUT PEX_RUNDOWN_REF RunRef
178 ExfAcquireRundownProtectionEx(
179 IN OUT PEX_RUNDOWN_REF RunRef
,
185 ExfReleaseRundownProtection(
186 IN OUT PEX_RUNDOWN_REF RunRef
191 ExfReleaseRundownProtectionEx(
192 IN OUT PEX_RUNDOWN_REF RunRef
,
199 OUT PEX_RUNDOWN_REF RunRef
204 ExfWaitForRundownProtectionRelease(
205 IN OUT PEX_RUNDOWN_REF RunRef
208 /* HANDLE TABLE FUNCTIONS ***************************************************/
210 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
211 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
212 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
213 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
215 #define EX_HANDLE_TABLE_CLOSING 0x1
217 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
218 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
219 EX_HANDLE_ENTRY_INHERITABLE | \
220 EX_HANDLE_ENTRY_AUDITONCLOSE)
222 typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK
)(
223 PHANDLE_TABLE_ENTRY HandleTableEntry
,
228 typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK
)(
229 PHANDLE_TABLE HandleTable
,
230 PHANDLE_TABLE_ENTRY HandleTableEntry
,
234 typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK
)(
235 PHANDLE_TABLE HandleTable
,
236 PHANDLE_TABLE_ENTRY HandleTableEntry
,
241 ExpInitializeHandleTables(VOID
);
244 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL
);
247 ExDestroyHandleTable(
248 IN PHANDLE_TABLE HandleTable
253 IN PHANDLE_TABLE HandleTable
,
254 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL
,
255 IN PVOID Context OPTIONAL
260 IN PEPROCESS QuotaProcess OPTIONAL
,
261 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL
,
262 IN PVOID Context OPTIONAL
,
263 IN PHANDLE_TABLE SourceHandleTable
267 ExLockHandleTableEntry(
268 IN PHANDLE_TABLE HandleTable
,
269 IN PHANDLE_TABLE_ENTRY Entry
273 ExUnlockHandleTableEntry(
274 IN PHANDLE_TABLE HandleTable
,
275 IN PHANDLE_TABLE_ENTRY Entry
280 IN PHANDLE_TABLE HandleTable
,
281 IN PHANDLE_TABLE_ENTRY Entry
286 IN PHANDLE_TABLE HandleTable
,
291 ExDestroyHandleByEntry(
292 IN PHANDLE_TABLE HandleTable
,
293 IN PHANDLE_TABLE_ENTRY Entry
,
298 ExMapHandleToPointer(
299 IN PHANDLE_TABLE HandleTable
,
305 IN PHANDLE_TABLE HandleTable
,
307 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback
,
311 /* PSEH EXCEPTION HANDLING **************************************************/
315 ExSystemExceptionFilter(VOID
);
317 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
319 return ExSystemExceptionFilter();
322 /* RUNDOWN *******************************************************************/
325 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
326 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
328 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
329 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
330 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
334 * @name ExfAcquireRundownProtection
337 * The ExfAcquireRundownProtection routine acquires rundown protection for
338 * the specified descriptor.
341 * Pointer to a rundown reference descriptor.
343 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
345 * @remarks This is the internal macro for system use only.In case the rundown
346 * was active, then the slow-path will be called through the exported
352 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
354 ULONG_PTR Value
, NewValue
, OldValue
;
356 /* Get the current value and mask the active bit */
357 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
359 /* Add a reference */
360 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
362 /* Change the value */
363 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
364 if (OldValue
!= Value
)
366 /* Rundown was active, use long path */
367 return ExfAcquireRundownProtection(RunRef
);
375 * @name ExReleaseRundownProtection
378 * The ExReleaseRundownProtection routine releases rundown protection for
379 * the specified descriptor.
382 * Pointer to a rundown reference descriptor.
384 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
386 * @remarks This is the internal macro for system use only.In case the rundown
387 * was active, then the slow-path will be called through the exported
393 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
395 ULONG_PTR Value
, NewValue
, OldValue
;
397 /* Get the current value and mask the active bit */
398 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
400 /* Remove a reference */
401 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
403 /* Change the value */
404 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
406 /* Check if the rundown was active */
407 if (OldValue
!= Value
)
409 /* Rundown was active, use long path */
410 ExfReleaseRundownProtection(RunRef
);
415 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
420 * @name ExInitializeRundownProtection
423 * The ExInitializeRundownProtection routine initializes a rundown
424 * protection descriptor.
427 * Pointer to a rundown reference descriptor.
431 * @remarks This is the internal macro for system use only.
436 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
438 /* Set the count to zero */
443 * @name ExWaitForRundownProtectionRelease
446 * The ExWaitForRundownProtectionRelease routine waits until the specified
447 * rundown descriptor has been released.
450 * Pointer to a rundown reference descriptor.
454 * @remarks This is the internal macro for system use only. If a wait is actually
455 * necessary, then the slow path is taken through the exported function.
460 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
464 /* Set the active bit */
465 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
466 if ((Value
) || (Value
!= EX_RUNDOWN_ACTIVE
))
468 /* If the the rundown wasn't already active, then take the long path */
469 ExfWaitForRundownProtectionRelease(RunRef
);
474 * @name ExRundownCompleted
477 * The ExRundownCompleted routine completes the rundown of the specified
478 * descriptor by setting the active bit.
481 * Pointer to a rundown reference descriptor.
485 * @remarks This is the internal macro for system use only.
490 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
493 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
495 /* Mark the counter as active */
496 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
499 /* PUSHLOCKS *****************************************************************/
502 * @name ExInitializePushLock
505 * The ExInitializePushLock macro initializes a PushLock.
508 * Pointer to the pushlock which is to be initialized.
517 ExInitializePushLock(IN PEX_PUSH_LOCK PushLock
)
519 /* Set the value to 0 */
524 * @name ExAcquirePushLockExclusive
527 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
530 * Pointer to the pushlock which is to be acquired.
534 * @remarks The function attempts the quickest route to acquire the lock, which is
535 * to simply set the lock bit.
536 * However, if the pushlock is already shared, the slower path is taken.
538 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
539 * This macro should usually be paired up with KeAcquireCriticalRegion.
544 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
546 /* Try acquiring the lock */
547 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
549 /* Someone changed it, use the slow path */
550 DbgPrint("%s - Contention!\n", __FUNCTION__
);
551 ExfAcquirePushLockExclusive(PushLock
);
555 ASSERT(PushLock
->Locked
);
559 * @name ExAcquirePushLockShared
562 * The ExAcquirePushLockShared macro acquires a shared PushLock.
565 * Pointer to the pushlock which is to be acquired.
569 * @remarks The function attempts the quickest route to acquire the lock, which is
570 * to simply set the lock bit and set the share count to one.
571 * However, if the pushlock is already shared, the slower path is taken.
573 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
574 * This macro should usually be paired up with KeAcquireCriticalRegion.
579 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
581 EX_PUSH_LOCK NewValue
;
583 /* Try acquiring the lock */
584 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
585 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
587 /* Someone changed it, use the slow path */
588 DbgPrint("%s - Contention!\n", __FUNCTION__
);
589 ExfAcquirePushLockShared(PushLock
);
593 ASSERT(PushLock
->Locked
);
594 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
598 * @name ExConvertPushLockSharedToExclusive
601 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
602 * pushlock to a shared pushlock.
605 * Pointer to the pushlock which is to be converted.
607 * @return FALSE if conversion failed, TRUE otherwise.
609 * @remarks The function attempts the quickest route to convert the lock, which is
610 * to simply set the lock bit and remove any other bits.
615 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock
)
617 EX_PUSH_LOCK OldValue
;
619 /* Set the expected old value */
620 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
622 /* Try converting the lock */
623 if (ExpChangePushlock(PushLock
, EX_PUSH_LOCK_LOCK
, OldValue
.Value
) !=
626 /* Conversion failed */
631 ASSERT(PushLock
->Locked
);
636 * @name ExWaitOnPushLock
639 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
642 * Pointer to a pushlock.
646 * @remarks The function attempts to get any exclusive waiters out of their slow
647 * path by forcing an instant acquire/release operation.
649 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
654 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
656 /* Acquire the lock */
657 ExfAcquirePushLockExclusive(PushLock
);
658 ASSERT(PushLock
->Locked
);
661 ExfReleasePushLockExclusive(PushLock
);
665 * @name ExReleasePushLockShared
668 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
671 * Pointer to a previously acquired pushlock.
675 * @remarks The function attempts the quickest route to release the lock, which is
676 * to simply decrease the share count and remove the lock bit.
677 * However, if the pushlock is being waited on then the long path is taken.
679 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
680 * This macro should usually be paired up with KeLeaveCriticalRegion.
685 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
687 EX_PUSH_LOCK OldValue
;
690 ASSERT(PushLock
->Locked
);
691 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
693 /* Try to clear the pushlock */
694 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
695 if (ExpChangePushlock(PushLock
, 0, OldValue
.Ptr
) != OldValue
.Ptr
)
697 /* There are still other people waiting on it */
698 DbgPrint("%s - Contention!\n", __FUNCTION__
);
699 ExfReleasePushLockShared(PushLock
);
704 * @name ExReleasePushLockExclusive
707 * The ExReleasePushLockExclusive macro releases a previously
708 * exclusively acquired PushLock.
711 * Pointer to a previously acquired pushlock.
715 * @remarks The function attempts the quickest route to release the lock, which is
716 * to simply clear the locked bit.
717 * However, if the pushlock is being waited on, the slow path is taken
718 * in an attempt to wake up the lock.
720 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
721 * This macro should usually be paired up with KeLeaveCriticalRegion.
726 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
728 EX_PUSH_LOCK OldValue
;
731 ASSERT(PushLock
->Locked
);
732 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
734 /* Unlock the pushlock */
735 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
, -1);
738 ASSERT(OldValue
.Locked
);
739 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
741 /* Check if anyone is waiting on it and it's not already waking*/
742 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
745 DbgPrint("%s - Contention!\n", __FUNCTION__
);
746 ExfTryToWakePushLock(PushLock
);
751 * @name ExReleasePushLock
754 * The ExReleasePushLock macro releases a previously acquired PushLock.
757 * Pointer to a previously acquired pushlock.
761 * @remarks The function attempts the quickest route to release the lock, which is
762 * to simply clear all the fields and decrease the share count if required.
763 * However, if the pushlock is being waited on then the long path is taken.
765 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
766 * This macro should usually be paired up with KeLeaveCriticalRegion.
771 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
773 EX_PUSH_LOCK OldValue
= *PushLock
;
774 EX_PUSH_LOCK NewValue
;
777 ASSERT(OldValue
.Locked
);
779 /* Check if the pushlock is shared */
780 if (OldValue
.Shared
> 1)
782 /* Decrease the share count */
783 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
787 /* Clear the pushlock entirely */
791 /* Check if nobody is waiting on us and try clearing the lock here */
792 if ((OldValue
.Waiting
) ||
793 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) ==
796 /* We have waiters, use the long path */
797 DbgPrint("%s - Contention!\n", __FUNCTION__
);
798 ExfReleasePushLock(PushLock
);
802 /* OTHER FUNCTIONS **********************************************************/
806 ExfpInterlockedExchange64(
807 LONGLONG
volatile * Destination
,
812 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
816 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
820 ExTimerRundown(VOID
);
822 #define InterlockedDecrementUL(Addend) \
823 (ULONG)InterlockedDecrement((PLONG)(Addend))
825 #define InterlockedIncrementUL(Addend) \
826 (ULONG)InterlockedIncrement((PLONG)(Addend))
828 #define InterlockedExchangeUL(Target, Value) \
829 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
831 #define InterlockedExchangeAddUL(Addend, Value) \
832 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
834 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
835 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
837 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
838 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
840 #define ExfpInterlockedExchange64UL(Target, Value) \
841 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
843 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */