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 typedef struct _ETIMER
29 LIST_ENTRY ActiveTimerListEntry
;
32 BOOLEAN ApcAssociated
;
34 LIST_ENTRY WakeTimerListEntry
;
37 #define MAX_FAST_REFS 7
39 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
40 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
41 EX_HANDLE_ENTRY_AUDITONCLOSE)))
42 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->Object) & \
43 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
44 EX_HANDLE_ENTRY_AUDITONCLOSE)))
46 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
48 #define ExAcquireResourceLock(l, i) { \
52 #define ExReleaseResourceLock(l, i) _enable();
54 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
55 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
58 #define ExAcquireRundownProtection _ExAcquireRundownProtection
59 #define ExReleaseRundownProtection _ExReleaseRundownProtection
60 #define ExInitializeRundownProtection _ExInitializeRundownProtection
61 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
62 #define ExRundownCompleted _ExRundownCompleted
63 #define ExGetPreviousMode KeGetPreviousMode
65 /* INITIALIZATION FUNCTIONS *************************************************/
83 ExpInitializePushLocks(VOID
);
87 ExRefreshTimeZoneInformation(
88 IN PLARGE_INTEGER SystemBootTime
93 ExpInitializeWorkerThreads(VOID
);
97 ExpInitLookasideLists(VOID
);
101 ExInitializeSystemLookasideList(
102 IN PGENERAL_LOOKASIDE List
,
106 IN USHORT MaximumDepth
,
107 IN PLIST_ENTRY ListHead
112 ExpInitializeCallbacks(VOID
);
120 ExpInitializeExecutive(
122 IN PLOADER_PARAMETER_BLOCK LoaderBlock
127 ExpInitializeEventImplementation(VOID
);
131 ExpInitializeEventImplementation(VOID
);
135 ExpInitializeEventPairImplementation(VOID
);
139 ExpInitializeSemaphoreImplementation(VOID
);
143 ExpInitializeMutantImplementation(VOID
);
147 ExpInitializeTimerImplementation(VOID
);
151 ExpInitializeProfileImplementation(VOID
);
155 ExpResourceInitialization(VOID
);
159 ExInitPoolLookasidePointers(VOID
);
161 /* Callback Functions ********************************************************/
165 ExInitializeCallBack(
166 IN PEX_CALLBACK Callback
169 /* Rundown Functions ********************************************************/
173 ExfInitializeRundownProtection(
174 OUT PEX_RUNDOWN_REF RunRef
179 ExfReInitializeRundownProtection(
180 OUT PEX_RUNDOWN_REF RunRef
185 ExfAcquireRundownProtection(
186 IN OUT PEX_RUNDOWN_REF RunRef
191 ExfAcquireRundownProtectionEx(
192 IN OUT PEX_RUNDOWN_REF RunRef
,
198 ExfReleaseRundownProtection(
199 IN OUT PEX_RUNDOWN_REF RunRef
204 ExfReleaseRundownProtectionEx(
205 IN OUT PEX_RUNDOWN_REF RunRef
,
212 OUT PEX_RUNDOWN_REF RunRef
217 ExfWaitForRundownProtectionRelease(
218 IN OUT PEX_RUNDOWN_REF RunRef
221 /* HANDLE TABLE FUNCTIONS ***************************************************/
223 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
224 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
225 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
226 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
228 #define EX_HANDLE_TABLE_CLOSING 0x1
230 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
231 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
232 EX_HANDLE_ENTRY_INHERITABLE | \
233 EX_HANDLE_ENTRY_AUDITONCLOSE)
235 typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK
)(
236 PHANDLE_TABLE_ENTRY HandleTableEntry
,
241 typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK
)(
242 PHANDLE_TABLE HandleTable
,
243 PHANDLE_TABLE_ENTRY HandleTableEntry
,
247 typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK
)(
248 PHANDLE_TABLE HandleTable
,
249 PHANDLE_TABLE_ENTRY HandleTableEntry
,
254 ExpInitializeHandleTables(VOID
);
257 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL
);
260 ExDestroyHandleTable(
261 IN PHANDLE_TABLE HandleTable
266 IN PHANDLE_TABLE HandleTable
,
267 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL
,
268 IN PVOID Context OPTIONAL
273 IN PEPROCESS QuotaProcess OPTIONAL
,
274 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL
,
275 IN PVOID Context OPTIONAL
,
276 IN PHANDLE_TABLE SourceHandleTable
280 ExLockHandleTableEntry(
281 IN PHANDLE_TABLE HandleTable
,
282 IN PHANDLE_TABLE_ENTRY Entry
286 ExUnlockHandleTableEntry(
287 IN PHANDLE_TABLE HandleTable
,
288 IN PHANDLE_TABLE_ENTRY Entry
293 IN PHANDLE_TABLE HandleTable
,
294 IN PHANDLE_TABLE_ENTRY Entry
299 IN PHANDLE_TABLE HandleTable
,
304 ExDestroyHandleByEntry(
305 IN PHANDLE_TABLE HandleTable
,
306 IN PHANDLE_TABLE_ENTRY Entry
,
311 ExMapHandleToPointer(
312 IN PHANDLE_TABLE HandleTable
,
318 IN PHANDLE_TABLE HandleTable
,
320 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback
,
324 /* PSEH EXCEPTION HANDLING **************************************************/
328 ExSystemExceptionFilter(VOID
);
330 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
332 return ExSystemExceptionFilter();
335 /* RUNDOWN *******************************************************************/
338 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
339 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
341 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
342 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
343 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
347 * @name ExfAcquireRundownProtection
350 * The ExfAcquireRundownProtection routine acquires rundown protection for
351 * the specified descriptor.
354 * Pointer to a rundown reference descriptor.
356 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
358 * @remarks This is the internal macro for system use only.In case the rundown
359 * was active, then the slow-path will be called through the exported
365 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
367 ULONG_PTR Value
, NewValue
, OldValue
;
369 /* Get the current value and mask the active bit */
370 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
372 /* Add a reference */
373 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
375 /* Change the value */
376 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
377 if (OldValue
!= Value
)
379 /* Rundown was active, use long path */
380 return ExfAcquireRundownProtection(RunRef
);
388 * @name ExReleaseRundownProtection
391 * The ExReleaseRundownProtection routine releases rundown protection for
392 * the specified descriptor.
395 * Pointer to a rundown reference descriptor.
397 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
399 * @remarks This is the internal macro for system use only.In case the rundown
400 * was active, then the slow-path will be called through the exported
406 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
408 ULONG_PTR Value
, NewValue
, OldValue
;
410 /* Get the current value and mask the active bit */
411 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
413 /* Remove a reference */
414 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
416 /* Change the value */
417 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
419 /* Check if the rundown was active */
420 if (OldValue
!= Value
)
422 /* Rundown was active, use long path */
423 ExfReleaseRundownProtection(RunRef
);
428 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
433 * @name ExInitializeRundownProtection
436 * The ExInitializeRundownProtection routine initializes a rundown
437 * protection descriptor.
440 * Pointer to a rundown reference descriptor.
444 * @remarks This is the internal macro for system use only.
449 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
451 /* Set the count to zero */
456 * @name ExWaitForRundownProtectionRelease
459 * The ExWaitForRundownProtectionRelease routine waits until the specified
460 * rundown descriptor has been released.
463 * Pointer to a rundown reference descriptor.
467 * @remarks This is the internal macro for system use only. If a wait is actually
468 * necessary, then the slow path is taken through the exported function.
473 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
477 /* Set the active bit */
478 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
479 if ((Value
) || (Value
!= EX_RUNDOWN_ACTIVE
))
481 /* If the the rundown wasn't already active, then take the long path */
482 ExfWaitForRundownProtectionRelease(RunRef
);
487 * @name ExRundownCompleted
490 * The ExRundownCompleted routine completes the rundown of the specified
491 * descriptor by setting the active bit.
494 * Pointer to a rundown reference descriptor.
498 * @remarks This is the internal macro for system use only.
503 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
506 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
508 /* Mark the counter as active */
509 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
512 /* PUSHLOCKS *****************************************************************/
515 * @name ExInitializePushLock
518 * The ExInitializePushLock macro initializes a PushLock.
521 * Pointer to the pushlock which is to be initialized.
530 ExInitializePushLock(IN PULONG_PTR PushLock
)
532 /* Set the value to 0 */
537 * @name ExAcquirePushLockExclusive
540 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
543 * Pointer to the pushlock which is to be acquired.
547 * @remarks The function attempts the quickest route to acquire the lock, which is
548 * to simply set the lock bit.
549 * However, if the pushlock is already shared, the slower path is taken.
551 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
552 * This macro should usually be paired up with KeAcquireCriticalRegion.
557 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
559 /* Try acquiring the lock */
560 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
562 /* Someone changed it, use the slow path */
563 DbgPrint("%s - Contention!\n", __FUNCTION__
);
564 ExfAcquirePushLockExclusive(PushLock
);
568 ASSERT(PushLock
->Locked
);
572 * @name ExAcquirePushLockShared
575 * The ExAcquirePushLockShared macro acquires a shared PushLock.
578 * Pointer to the pushlock which is to be acquired.
582 * @remarks The function attempts the quickest route to acquire the lock, which is
583 * to simply set the lock bit and set the share count to one.
584 * However, if the pushlock is already shared, the slower path is taken.
586 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
587 * This macro should usually be paired up with KeAcquireCriticalRegion.
592 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
594 EX_PUSH_LOCK NewValue
;
596 /* Try acquiring the lock */
597 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
598 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
600 /* Someone changed it, use the slow path */
601 DbgPrint("%s - Contention!\n", __FUNCTION__
);
602 ExfAcquirePushLockShared(PushLock
);
606 ASSERT(PushLock
->Locked
);
607 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
611 * @name ExConvertPushLockSharedToExclusive
614 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
615 * pushlock to a shared pushlock.
618 * Pointer to the pushlock which is to be converted.
620 * @return FALSE if conversion failed, TRUE otherwise.
622 * @remarks The function attempts the quickest route to convert the lock, which is
623 * to simply set the lock bit and remove any other bits.
628 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock
)
630 EX_PUSH_LOCK OldValue
;
632 /* Set the expected old value */
633 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
635 /* Try converting the lock */
636 if (ExpChangePushlock(PushLock
, EX_PUSH_LOCK_LOCK
, OldValue
.Value
) !=
639 /* Conversion failed */
644 ASSERT(PushLock
->Locked
);
649 * @name ExWaitOnPushLock
652 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
655 * Pointer to a pushlock.
659 * @remarks The function attempts to get any exclusive waiters out of their slow
660 * path by forcing an instant acquire/release operation.
662 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
667 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
669 /* Acquire the lock */
670 ExfAcquirePushLockExclusive(PushLock
);
671 ASSERT(PushLock
->Locked
);
674 ExfReleasePushLockExclusive(PushLock
);
678 * @name ExReleasePushLockShared
681 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
684 * Pointer to a previously acquired pushlock.
688 * @remarks The function attempts the quickest route to release the lock, which is
689 * to simply decrease the share count and remove the lock bit.
690 * However, if the pushlock is being waited on then the long path is taken.
692 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
693 * This macro should usually be paired up with KeLeaveCriticalRegion.
698 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
700 EX_PUSH_LOCK OldValue
;
703 ASSERT(PushLock
->Locked
);
704 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
706 /* Try to clear the pushlock */
707 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
708 if (ExpChangePushlock(PushLock
, 0, OldValue
.Ptr
) != OldValue
.Ptr
)
710 /* There are still other people waiting on it */
711 DbgPrint("%s - Contention!\n", __FUNCTION__
);
712 ExfReleasePushLockShared(PushLock
);
717 * @name ExReleasePushLockExclusive
720 * The ExReleasePushLockExclusive macro releases a previously
721 * exclusively acquired PushLock.
724 * Pointer to a previously acquired pushlock.
728 * @remarks The function attempts the quickest route to release the lock, which is
729 * to simply clear the locked bit.
730 * However, if the pushlock is being waited on, the slow path is taken
731 * in an attempt to wake up the lock.
733 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
734 * This macro should usually be paired up with KeLeaveCriticalRegion.
739 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
741 EX_PUSH_LOCK OldValue
;
744 ASSERT(PushLock
->Locked
);
745 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
747 /* Unlock the pushlock */
748 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
, -1);
751 ASSERT(OldValue
.Locked
);
752 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
754 /* Check if anyone is waiting on it and it's not already waking*/
755 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
758 DbgPrint("%s - Contention!\n", __FUNCTION__
);
759 ExfTryToWakePushLock(PushLock
);
764 * @name ExReleasePushLock
767 * The ExReleasePushLock macro releases a previously acquired PushLock.
770 * Pointer to a previously acquired pushlock.
774 * @remarks The function attempts the quickest route to release the lock, which is
775 * to simply clear all the fields and decrease the share count if required.
776 * However, if the pushlock is being waited on then the long path is taken.
778 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
779 * This macro should usually be paired up with KeLeaveCriticalRegion.
784 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
786 EX_PUSH_LOCK OldValue
= *PushLock
;
787 EX_PUSH_LOCK NewValue
;
790 ASSERT(OldValue
.Locked
);
792 /* Check if the pushlock is shared */
793 if (OldValue
.Shared
> 1)
795 /* Decrease the share count */
796 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
800 /* Clear the pushlock entirely */
804 /* Check if nobody is waiting on us and try clearing the lock here */
805 if ((OldValue
.Waiting
) ||
806 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) !=
809 /* We have waiters, use the long path */
810 DbgPrint("%s - Contention!\n", __FUNCTION__
);
811 ExfReleasePushLock(PushLock
);
815 /* OTHER FUNCTIONS **********************************************************/
819 ExfpInterlockedExchange64(
820 LONGLONG
volatile * Destination
,
825 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
829 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
833 ExTimerRundown(VOID
);
835 #define InterlockedDecrementUL(Addend) \
836 (ULONG)InterlockedDecrement((PLONG)(Addend))
838 #define InterlockedIncrementUL(Addend) \
839 (ULONG)InterlockedIncrement((PLONG)(Addend))
841 #define InterlockedExchangeUL(Target, Value) \
842 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
844 #define InterlockedExchangeAddUL(Addend, Value) \
845 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
847 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
848 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
850 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
851 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
853 #define ExfpInterlockedExchange64UL(Target, Value) \
854 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
856 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */