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 POBJECT_TYPE ExEventPairObjectType
;
11 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
12 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
13 EX_HANDLE_ENTRY_AUDITONCLOSE)))
14 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \
15 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
16 EX_HANDLE_ENTRY_AUDITONCLOSE)))
18 /* INITIALIZATION FUNCTIONS *************************************************/
30 ExpInitTimeZoneInfo(VOID
);
34 ExpInitializeWorkerThreads(VOID
);
38 ExpInitLookasideLists(VOID
);
42 ExpInitializeCallbacks(VOID
);
50 ExpInitializeExecutive(VOID
);
54 ExpInitializeEventImplementation(VOID
);
58 ExpInitializeEventImplementation(VOID
);
62 ExpInitializeEventPairImplementation(VOID
);
66 ExpInitializeSemaphoreImplementation(VOID
);
70 ExpInitializeMutantImplementation(VOID
);
74 ExpInitializeTimerImplementation(VOID
);
78 ExpInitializeProfileImplementation(VOID
);
80 /* Rundown Functions ********************************************************/
84 ExfInitializeRundownProtection(
85 OUT PEX_RUNDOWN_REF RunRef
90 ExfReInitializeRundownProtection(
91 OUT PEX_RUNDOWN_REF RunRef
96 ExfAcquireRundownProtection(
97 IN OUT PEX_RUNDOWN_REF RunRef
102 ExfAcquireRundownProtectionEx(
103 IN OUT PEX_RUNDOWN_REF RunRef
,
109 ExfReleaseRundownProtection(
110 IN OUT PEX_RUNDOWN_REF RunRef
115 ExfReleaseRundownProtectionEx(
116 IN OUT PEX_RUNDOWN_REF RunRef
,
123 OUT PEX_RUNDOWN_REF RunRef
128 ExfWaitForRundownProtectionRelease(
129 IN OUT PEX_RUNDOWN_REF RunRef
132 /* HANDLE TABLE FUNCTIONS ***************************************************/
134 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
135 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
136 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
137 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
139 #define EX_HANDLE_TABLE_CLOSING 0x1
141 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
142 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
143 EX_HANDLE_ENTRY_INHERITABLE | \
144 EX_HANDLE_ENTRY_AUDITONCLOSE)
146 typedef VOID (STDCALL PEX_SWEEP_HANDLE_CALLBACK
)(
147 PHANDLE_TABLE HandleTable
,
153 typedef BOOLEAN (STDCALL PEX_DUPLICATE_HANDLE_CALLBACK
)(
154 PHANDLE_TABLE HandleTable
,
155 PHANDLE_TABLE_ENTRY HandleTableEntry
,
159 typedef BOOLEAN (STDCALL PEX_CHANGE_HANDLE_CALLBACK
)(
160 PHANDLE_TABLE HandleTable
,
161 PHANDLE_TABLE_ENTRY HandleTableEntry
,
166 ExpInitializeHandleTables(VOID
);
169 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL
);
172 ExDestroyHandleTable(
173 IN PHANDLE_TABLE HandleTable
178 IN PHANDLE_TABLE HandleTable
,
179 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL
,
180 IN PVOID Context OPTIONAL
185 IN PEPROCESS QuotaProcess OPTIONAL
,
186 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL
,
187 IN PVOID Context OPTIONAL
,
188 IN PHANDLE_TABLE SourceHandleTable
192 ExLockHandleTableEntry(
193 IN PHANDLE_TABLE HandleTable
,
194 IN PHANDLE_TABLE_ENTRY Entry
198 ExUnlockHandleTableEntry(
199 IN PHANDLE_TABLE HandleTable
,
200 IN PHANDLE_TABLE_ENTRY Entry
205 IN PHANDLE_TABLE HandleTable
,
206 IN PHANDLE_TABLE_ENTRY Entry
211 IN PHANDLE_TABLE HandleTable
,
216 ExDestroyHandleByEntry(
217 IN PHANDLE_TABLE HandleTable
,
218 IN PHANDLE_TABLE_ENTRY Entry
,
223 ExMapHandleToPointer(
224 IN PHANDLE_TABLE HandleTable
,
230 IN PHANDLE_TABLE HandleTable
,
232 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback
,
236 /* PSEH EXCEPTION HANDLING **************************************************/
240 ExSystemExceptionFilter(VOID
);
242 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
244 return ExSystemExceptionFilter();
247 /* RUNDOWN *******************************************************************/
250 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
251 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
253 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, y, z)
254 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
258 * @name ExfAcquireRundownProtection
261 * The ExfAcquireRundownProtection routine acquires rundown protection for
262 * the specified descriptor.
265 * Pointer to a rundown reference descriptor.
267 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
269 * @remarks This is the internal macro for system use only.In case the rundown
270 * was active, then the slow-path will be called through the exported
276 ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
278 ULONG_PTR Value
, NewValue
, OldValue
;
280 /* Get the current value and mask the active bit */
281 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
283 /* Add a reference */
284 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
286 /* Change the value */
287 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
288 if (OldValue
!= Value
)
290 /* Rundown was active, use long path */
291 return ExfAcquireRundownProtection(RunRef
);
299 * @name ExReleaseRundownProtection
302 * The ExReleaseRundownProtection routine releases rundown protection for
303 * the specified descriptor.
306 * Pointer to a rundown reference descriptor.
308 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
310 * @remarks This is the internal macro for system use only.In case the rundown
311 * was active, then the slow-path will be called through the exported
317 ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
319 ULONG_PTR Value
, NewValue
, OldValue
;
321 /* Get the current value and mask the active bit */
322 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
324 /* Remove a reference */
325 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
327 /* Change the value */
328 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
330 /* Check if the rundown was active */
331 if (OldValue
!= Value
)
333 /* Rundown was active, use long path */
334 ExfReleaseRundownProtection(RunRef
);
339 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
344 * @name ExInitializeRundownProtection
347 * The ExInitializeRundownProtection routine initializes a rundown
348 * protection descriptor.
351 * Pointer to a rundown reference descriptor.
355 * @remarks This is the internal macro for system use only.
360 ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
362 /* Set the count to zero */
367 * @name ExWaitForRundownProtectionRelease
370 * The ExWaitForRundownProtectionRelease routine waits until the specified
371 * rundown descriptor has been released.
374 * Pointer to a rundown reference descriptor.
378 * @remarks This is the internal macro for system use only. If a wait is actually
379 * necessary, then the slow path is taken through the exported function.
384 ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
388 /* Set the active bit */
389 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
390 if ((Value
) || (Value
!= EX_RUNDOWN_ACTIVE
))
392 /* If the the rundown wasn't already active, then take the long path */
393 ExfWaitForRundownProtectionRelease(RunRef
);
398 * @name ExRundownCompleted
401 * The ExRundownCompleted routine completes the rundown of the specified
402 * descriptor by setting the active bit.
405 * Pointer to a rundown reference descriptor.
409 * @remarks This is the internal macro for system use only.
414 ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
417 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
419 /* Mark the counter as active */
420 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
423 /* PUSHLOCKS *****************************************************************/
426 * @name ExAcquirePushLockExclusive
429 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
432 * Pointer to the pushlock which is to be acquired.
436 * @remarks The function attempts the quickest route to acquire the lock, which is
437 * to simply set the lock bit.
438 * However, if the pushlock is already shared, the slower path is taken.
440 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
441 * This macro should usually be paired up with KeAcquireCriticalRegion.
446 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
448 /* Try acquiring the lock */
449 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
451 /* Someone changed it, use the slow path */
452 ExfAcquirePushLockExclusive(PushLock
);
456 ASSERT(PushLock
->Locked
);
460 * @name ExAcquirePushLockShared
463 * The ExAcquirePushLockShared macro acquires a shared PushLock.
466 * Pointer to the pushlock which is to be acquired.
470 * @remarks The function attempts the quickest route to acquire the lock, which is
471 * to simply set the lock bit and set the share count to one.
472 * However, if the pushlock is already shared, the slower path is taken.
474 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
475 * This macro should usually be paired up with KeAcquireCriticalRegion.
480 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
482 EX_PUSH_LOCK NewValue
;
484 /* Try acquiring the lock */
485 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
486 if (!InterlockedCompareExchangePointer(PushLock
, NewValue
.Ptr
, 0))
488 /* Someone changed it, use the slow path */
489 ExfAcquirePushLockShared(PushLock
);
493 ASSERT(PushLock
->Locked
);
494 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
498 * @name ExWaitOnPushLock
501 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
504 * Pointer to a pushlock.
508 * @remarks The function attempts to get any exclusive waiters out of their slow
509 * path by forcing an instant acquire/release operation.
511 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
516 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
518 /* Acquire the lock */
519 ExfAcquirePushLockExclusive(PushLock
);
520 ASSERT(PushLock
->Locked
);
523 ExfReleasePushLockExclusive(PushLock
);
527 * @name ExReleasePushLockShared
530 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
533 * Pointer to a previously acquired pushlock.
537 * @remarks The function attempts the quickest route to release the lock, which is
538 * to simply decrease the share count and remove the lock bit.
539 * However, if the pushlock is being waited on then the long path is taken.
541 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
542 * This macro should usually be paired up with KeLeaveCriticalRegion.
547 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
549 EX_PUSH_LOCK OldValue
;
552 ASSERT(PushLock
->Locked
);
553 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
555 /* Try to clear the pushlock */
556 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
557 if (InterlockedCompareExchangePointer(PushLock
, 0, OldValue
.Ptr
) !=
560 /* There are still other people waiting on it */
561 ExfReleasePushLockShared(PushLock
);
566 * @name ExReleasePushLockExclusive
569 * The ExReleasePushLockExclusive macro releases a previously
570 * exclusively acquired PushLock.
573 * Pointer to a previously acquired pushlock.
577 * @remarks The function attempts the quickest route to release the lock, which is
578 * to simply clear the locked bit.
579 * However, if the pushlock is being waited on, the slow path is taken
580 * in an attempt to wake up the lock.
582 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
583 * This macro should usually be paired up with KeLeaveCriticalRegion.
588 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
590 EX_PUSH_LOCK OldValue
;
593 ASSERT(PushLock
->Locked
);
594 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
596 /* Unlock the pushlock */
597 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
, -1);
600 ASSERT(OldValue
.Locked
);
601 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
603 /* Check if anyone is waiting on it and it's not already waking*/
604 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
607 ExfTryToWakePushLock(PushLock
);
612 * @name ExReleasePushLock
615 * The ExReleasePushLock macro releases a previously acquired PushLock.
618 * Pointer to a previously acquired pushlock.
622 * @remarks The function attempts the quickest route to release the lock, which is
623 * to simply clear all the fields and decrease the share count if required.
624 * However, if the pushlock is being waited on then the long path is taken.
626 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
627 * This macro should usually be paired up with KeLeaveCriticalRegion.
632 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
634 EX_PUSH_LOCK OldValue
= *PushLock
;
635 EX_PUSH_LOCK NewValue
;
638 ASSERT(OldValue
.Locked
);
640 /* Check if the pushlock is shared */
641 if (OldValue
.Shared
> 1)
643 /* Decrease the share count */
644 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
648 /* Clear the pushlock entirely */
652 /* Check if nobody is waiting on us and try clearing the lock here */
653 if ((OldValue
.Waiting
) ||
654 (InterlockedCompareExchangePointer(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) ==
657 /* We have waiters, use the long path */
658 ExfReleasePushLock(PushLock
);
662 /* OTHER FUNCTIONS **********************************************************/
666 ExfpInterlockedExchange64(
667 LONGLONG
volatile * Destination
,
672 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
676 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
680 ExTimerRundown(VOID
);
682 #define InterlockedDecrementUL(Addend) \
683 (ULONG)InterlockedDecrement((PLONG)(Addend))
685 #define InterlockedIncrementUL(Addend) \
686 (ULONG)InterlockedIncrement((PLONG)(Addend))
688 #define InterlockedExchangeUL(Target, Value) \
689 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
691 #define InterlockedExchangeAddUL(Addend, Value) \
692 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
694 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
695 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
697 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
698 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
700 #define ExfpInterlockedExchange64UL(Target, Value) \
701 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
703 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */