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 POBJECT_TYPE ExEventPairObjectType
;
11 extern ULONG NtBuildNumber
;
12 extern ULONG NtMajorVersion
;
13 extern ULONG NtMinorVersion
;
14 extern FAST_MUTEX ExpEnvironmentLock
;
15 extern ERESOURCE ExpFirmwareTableResource
;
16 extern LIST_ENTRY ExpFirmwareTableProviderListHead
;
17 extern BOOLEAN ExpIsWinPEMode
;
18 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
19 ULONG ExpUnicodeCaseTableDataOffset
;
20 PVOID ExpNlsSectionPointer
;
22 #define MAX_FAST_REFS 7
24 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
25 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
26 EX_HANDLE_ENTRY_AUDITONCLOSE)))
27 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->Object) & \
28 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
29 EX_HANDLE_ENTRY_AUDITONCLOSE)))
31 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
34 #define ExAcquireResourceLock(l, i) { \
36 Ke386DisableInterrupts(); \
38 #define ExReleaseResourceLock(l, i) Ke386EnableInterrupts();
40 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
41 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
42 #endif /* CONFIG_SMP */
43 #elif defined(_M_PPC) /* _M_IX86 */
45 #define ExAcquireResourceLock(l,i) KeAcquireSpinLock(l,i);
46 #define ExReleaseResourceLock(l,i) KeReleaseSpinLock(l,i);
49 #define ExAcquireRundownProtection _ExAcquireRundownProtection
50 #define ExReleaseRundownProtection _ExReleaseRundownProtection
51 #define ExInitializeRundownProtection _ExInitializeRundownProtection
52 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
53 #define ExRundownCompleted _ExRundownCompleted
55 /* INITIALIZATION FUNCTIONS *************************************************/
73 ExpInitializePushLocks(VOID
);
77 ExpInitTimeZoneInfo(VOID
);
81 ExpInitializeWorkerThreads(VOID
);
85 ExpInitLookasideLists(VOID
);
89 ExInitializeSystemLookasideList(
90 IN PGENERAL_LOOKASIDE List
,
94 IN USHORT MaximumDepth
,
95 IN PLIST_ENTRY ListHead
100 ExpInitializeCallbacks(VOID
);
108 ExpInitializeExecutive(
110 IN PLOADER_PARAMETER_BLOCK LoaderBlock
115 ExpInitializeEventImplementation(VOID
);
119 ExpInitializeEventImplementation(VOID
);
123 ExpInitializeEventPairImplementation(VOID
);
127 ExpInitializeSemaphoreImplementation(VOID
);
131 ExpInitializeMutantImplementation(VOID
);
135 ExpInitializeTimerImplementation(VOID
);
139 ExpInitializeProfileImplementation(VOID
);
143 ExpResourceInitialization(VOID
);
147 ExInitPoolLookasidePointers(VOID
);
149 /* Callback Functions ********************************************************/
153 ExInitializeCallBack(
154 IN PEX_CALLBACK Callback
157 /* Rundown Functions ********************************************************/
161 ExfInitializeRundownProtection(
162 OUT PEX_RUNDOWN_REF RunRef
167 ExfReInitializeRundownProtection(
168 OUT PEX_RUNDOWN_REF RunRef
173 ExfAcquireRundownProtection(
174 IN OUT PEX_RUNDOWN_REF RunRef
179 ExfAcquireRundownProtectionEx(
180 IN OUT PEX_RUNDOWN_REF RunRef
,
186 ExfReleaseRundownProtection(
187 IN OUT PEX_RUNDOWN_REF RunRef
192 ExfReleaseRundownProtectionEx(
193 IN OUT PEX_RUNDOWN_REF RunRef
,
200 OUT PEX_RUNDOWN_REF RunRef
205 ExfWaitForRundownProtectionRelease(
206 IN OUT PEX_RUNDOWN_REF RunRef
209 /* HANDLE TABLE FUNCTIONS ***************************************************/
211 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
212 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
213 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
214 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
216 #define EX_HANDLE_TABLE_CLOSING 0x1
218 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
219 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
220 EX_HANDLE_ENTRY_INHERITABLE | \
221 EX_HANDLE_ENTRY_AUDITONCLOSE)
223 typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK
)(
224 PHANDLE_TABLE_ENTRY HandleTableEntry
,
229 typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK
)(
230 PHANDLE_TABLE HandleTable
,
231 PHANDLE_TABLE_ENTRY HandleTableEntry
,
235 typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK
)(
236 PHANDLE_TABLE HandleTable
,
237 PHANDLE_TABLE_ENTRY HandleTableEntry
,
242 ExpInitializeHandleTables(VOID
);
245 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL
);
248 ExDestroyHandleTable(
249 IN PHANDLE_TABLE HandleTable
254 IN PHANDLE_TABLE HandleTable
,
255 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL
,
256 IN PVOID Context OPTIONAL
261 IN PEPROCESS QuotaProcess OPTIONAL
,
262 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL
,
263 IN PVOID Context OPTIONAL
,
264 IN PHANDLE_TABLE SourceHandleTable
268 ExLockHandleTableEntry(
269 IN PHANDLE_TABLE HandleTable
,
270 IN PHANDLE_TABLE_ENTRY Entry
274 ExUnlockHandleTableEntry(
275 IN PHANDLE_TABLE HandleTable
,
276 IN PHANDLE_TABLE_ENTRY Entry
281 IN PHANDLE_TABLE HandleTable
,
282 IN PHANDLE_TABLE_ENTRY Entry
287 IN PHANDLE_TABLE HandleTable
,
292 ExDestroyHandleByEntry(
293 IN PHANDLE_TABLE HandleTable
,
294 IN PHANDLE_TABLE_ENTRY Entry
,
299 ExMapHandleToPointer(
300 IN PHANDLE_TABLE HandleTable
,
306 IN PHANDLE_TABLE HandleTable
,
308 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback
,
312 /* PSEH EXCEPTION HANDLING **************************************************/
316 ExSystemExceptionFilter(VOID
);
318 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
320 return ExSystemExceptionFilter();
323 /* RUNDOWN *******************************************************************/
326 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
327 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
329 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
330 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
331 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
335 * @name ExfAcquireRundownProtection
338 * The ExfAcquireRundownProtection routine acquires rundown protection for
339 * the specified descriptor.
342 * Pointer to a rundown reference descriptor.
344 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
346 * @remarks This is the internal macro for system use only.In case the rundown
347 * was active, then the slow-path will be called through the exported
353 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
355 ULONG_PTR Value
, NewValue
, OldValue
;
357 /* Get the current value and mask the active bit */
358 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
360 /* Add a reference */
361 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
363 /* Change the value */
364 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
365 if (OldValue
!= Value
)
367 /* Rundown was active, use long path */
368 return ExfAcquireRundownProtection(RunRef
);
376 * @name ExReleaseRundownProtection
379 * The ExReleaseRundownProtection routine releases rundown protection for
380 * the specified descriptor.
383 * Pointer to a rundown reference descriptor.
385 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
387 * @remarks This is the internal macro for system use only.In case the rundown
388 * was active, then the slow-path will be called through the exported
394 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
396 ULONG_PTR Value
, NewValue
, OldValue
;
398 /* Get the current value and mask the active bit */
399 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
401 /* Remove a reference */
402 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
404 /* Change the value */
405 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
407 /* Check if the rundown was active */
408 if (OldValue
!= Value
)
410 /* Rundown was active, use long path */
411 ExfReleaseRundownProtection(RunRef
);
416 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
421 * @name ExInitializeRundownProtection
424 * The ExInitializeRundownProtection routine initializes a rundown
425 * protection descriptor.
428 * Pointer to a rundown reference descriptor.
432 * @remarks This is the internal macro for system use only.
437 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
439 /* Set the count to zero */
444 * @name ExWaitForRundownProtectionRelease
447 * The ExWaitForRundownProtectionRelease routine waits until the specified
448 * rundown descriptor has been released.
451 * Pointer to a rundown reference descriptor.
455 * @remarks This is the internal macro for system use only. If a wait is actually
456 * necessary, then the slow path is taken through the exported function.
461 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
465 /* Set the active bit */
466 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
467 if ((Value
) || (Value
!= EX_RUNDOWN_ACTIVE
))
469 /* If the the rundown wasn't already active, then take the long path */
470 ExfWaitForRundownProtectionRelease(RunRef
);
475 * @name ExRundownCompleted
478 * The ExRundownCompleted routine completes the rundown of the specified
479 * descriptor by setting the active bit.
482 * Pointer to a rundown reference descriptor.
486 * @remarks This is the internal macro for system use only.
491 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
494 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
496 /* Mark the counter as active */
497 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
500 /* PUSHLOCKS *****************************************************************/
503 * @name ExInitializePushLock
506 * The ExInitializePushLock macro initializes a PushLock.
509 * Pointer to the pushlock which is to be initialized.
518 ExInitializePushLock(IN PEX_PUSH_LOCK PushLock
)
520 /* Set the value to 0 */
525 * @name ExAcquirePushLockExclusive
528 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
531 * Pointer to the pushlock which is to be acquired.
535 * @remarks The function attempts the quickest route to acquire the lock, which is
536 * to simply set the lock bit.
537 * However, if the pushlock is already shared, the slower path is taken.
539 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
540 * This macro should usually be paired up with KeAcquireCriticalRegion.
545 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
547 /* Try acquiring the lock */
548 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
550 /* Someone changed it, use the slow path */
551 DbgPrint("%s - Contention!\n", __FUNCTION__
);
552 ExfAcquirePushLockExclusive(PushLock
);
556 ASSERT(PushLock
->Locked
);
560 * @name ExAcquirePushLockShared
563 * The ExAcquirePushLockShared macro acquires a shared PushLock.
566 * Pointer to the pushlock which is to be acquired.
570 * @remarks The function attempts the quickest route to acquire the lock, which is
571 * to simply set the lock bit and set the share count to one.
572 * However, if the pushlock is already shared, the slower path is taken.
574 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
575 * This macro should usually be paired up with KeAcquireCriticalRegion.
580 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
582 EX_PUSH_LOCK NewValue
;
584 /* Try acquiring the lock */
585 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
586 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
588 /* Someone changed it, use the slow path */
589 DbgPrint("%s - Contention!\n", __FUNCTION__
);
590 ExfAcquirePushLockShared(PushLock
);
594 ASSERT(PushLock
->Locked
);
595 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
599 * @name ExConvertPushLockSharedToExclusive
602 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
603 * pushlock to a shared pushlock.
606 * Pointer to the pushlock which is to be converted.
608 * @return FALSE if conversion failed, TRUE otherwise.
610 * @remarks The function attempts the quickest route to convert the lock, which is
611 * to simply set the lock bit and remove any other bits.
616 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock
)
618 EX_PUSH_LOCK OldValue
;
620 /* Set the expected old value */
621 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
623 /* Try converting the lock */
624 if (ExpChangePushlock(PushLock
, EX_PUSH_LOCK_LOCK
, OldValue
.Value
) !=
627 /* Conversion failed */
632 ASSERT(PushLock
->Locked
);
637 * @name ExWaitOnPushLock
640 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
643 * Pointer to a pushlock.
647 * @remarks The function attempts to get any exclusive waiters out of their slow
648 * path by forcing an instant acquire/release operation.
650 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
655 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
657 /* Acquire the lock */
658 ExfAcquirePushLockExclusive(PushLock
);
659 ASSERT(PushLock
->Locked
);
662 ExfReleasePushLockExclusive(PushLock
);
666 * @name ExReleasePushLockShared
669 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
672 * Pointer to a previously acquired pushlock.
676 * @remarks The function attempts the quickest route to release the lock, which is
677 * to simply decrease the share count and remove the lock bit.
678 * However, if the pushlock is being waited on then the long path is taken.
680 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
681 * This macro should usually be paired up with KeLeaveCriticalRegion.
686 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
688 EX_PUSH_LOCK OldValue
;
691 ASSERT(PushLock
->Locked
);
692 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
694 /* Try to clear the pushlock */
695 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
696 if (ExpChangePushlock(PushLock
, 0, OldValue
.Ptr
) != OldValue
.Ptr
)
698 /* There are still other people waiting on it */
699 DbgPrint("%s - Contention!\n", __FUNCTION__
);
700 ExfReleasePushLockShared(PushLock
);
705 * @name ExReleasePushLockExclusive
708 * The ExReleasePushLockExclusive macro releases a previously
709 * exclusively acquired PushLock.
712 * Pointer to a previously acquired pushlock.
716 * @remarks The function attempts the quickest route to release the lock, which is
717 * to simply clear the locked bit.
718 * However, if the pushlock is being waited on, the slow path is taken
719 * in an attempt to wake up the lock.
721 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
722 * This macro should usually be paired up with KeLeaveCriticalRegion.
727 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
729 EX_PUSH_LOCK OldValue
;
732 ASSERT(PushLock
->Locked
);
733 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
735 /* Unlock the pushlock */
736 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
, -1);
739 ASSERT(OldValue
.Locked
);
740 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
742 /* Check if anyone is waiting on it and it's not already waking*/
743 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
746 DbgPrint("%s - Contention!\n", __FUNCTION__
);
747 ExfTryToWakePushLock(PushLock
);
752 * @name ExReleasePushLock
755 * The ExReleasePushLock macro releases a previously acquired PushLock.
758 * Pointer to a previously acquired pushlock.
762 * @remarks The function attempts the quickest route to release the lock, which is
763 * to simply clear all the fields and decrease the share count if required.
764 * However, if the pushlock is being waited on then the long path is taken.
766 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
767 * This macro should usually be paired up with KeLeaveCriticalRegion.
772 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
774 EX_PUSH_LOCK OldValue
= *PushLock
;
775 EX_PUSH_LOCK NewValue
;
778 ASSERT(OldValue
.Locked
);
780 /* Check if the pushlock is shared */
781 if (OldValue
.Shared
> 1)
783 /* Decrease the share count */
784 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
788 /* Clear the pushlock entirely */
792 /* Check if nobody is waiting on us and try clearing the lock here */
793 if ((OldValue
.Waiting
) ||
794 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) ==
797 /* We have waiters, use the long path */
798 DbgPrint("%s - Contention!\n", __FUNCTION__
);
799 ExfReleasePushLock(PushLock
);
803 /* OTHER FUNCTIONS **********************************************************/
807 ExfpInterlockedExchange64(
808 LONGLONG
volatile * Destination
,
813 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
817 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
821 ExTimerRundown(VOID
);
823 #define InterlockedDecrementUL(Addend) \
824 (ULONG)InterlockedDecrement((PLONG)(Addend))
826 #define InterlockedIncrementUL(Addend) \
827 (ULONG)InterlockedIncrement((PLONG)(Addend))
829 #define InterlockedExchangeUL(Target, Value) \
830 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
832 #define InterlockedExchangeAddUL(Addend, Value) \
833 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
835 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
836 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
838 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
839 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
841 #define ExfpInterlockedExchange64UL(Target, Value) \
842 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
844 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */