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) ((PROS_OBJECT_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) ((PROS_OBJECT_HEADER)((ULONG_PTR)((hte)->Object) & \
15 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
16 EX_HANDLE_ENTRY_AUDITONCLOSE)))
18 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
20 #define ExAcquireResourceLock(l, i) { \
22 Ke386DisableInterrupts(); \
24 #define ExReleaseResourceLock(l, i) Ke386EnableInterrupts();
26 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
27 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
30 /* INITIALIZATION FUNCTIONS *************************************************/
42 ExpInitTimeZoneInfo(VOID
);
46 ExpInitializeWorkerThreads(VOID
);
50 ExpInitLookasideLists(VOID
);
54 ExpInitializeCallbacks(VOID
);
62 ExpInitializeExecutive(VOID
);
66 ExpInitializeEventImplementation(VOID
);
70 ExpInitializeEventImplementation(VOID
);
74 ExpInitializeEventPairImplementation(VOID
);
78 ExpInitializeSemaphoreImplementation(VOID
);
82 ExpInitializeMutantImplementation(VOID
);
86 ExpInitializeTimerImplementation(VOID
);
90 ExpInitializeProfileImplementation(VOID
);
94 ExpResourceInitialization(VOID
);
96 /* Rundown Functions ********************************************************/
100 ExfInitializeRundownProtection(
101 OUT PEX_RUNDOWN_REF RunRef
106 ExfReInitializeRundownProtection(
107 OUT PEX_RUNDOWN_REF RunRef
112 ExfAcquireRundownProtection(
113 IN OUT PEX_RUNDOWN_REF RunRef
118 ExfAcquireRundownProtectionEx(
119 IN OUT PEX_RUNDOWN_REF RunRef
,
125 ExfReleaseRundownProtection(
126 IN OUT PEX_RUNDOWN_REF RunRef
131 ExfReleaseRundownProtectionEx(
132 IN OUT PEX_RUNDOWN_REF RunRef
,
139 OUT PEX_RUNDOWN_REF RunRef
144 ExfWaitForRundownProtectionRelease(
145 IN OUT PEX_RUNDOWN_REF RunRef
148 /* HANDLE TABLE FUNCTIONS ***************************************************/
150 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
151 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
152 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
153 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
155 #define EX_HANDLE_TABLE_CLOSING 0x1
157 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
158 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
159 EX_HANDLE_ENTRY_INHERITABLE | \
160 EX_HANDLE_ENTRY_AUDITONCLOSE)
162 typedef VOID (STDCALL PEX_SWEEP_HANDLE_CALLBACK
)(
163 PHANDLE_TABLE HandleTable
,
169 typedef BOOLEAN (STDCALL PEX_DUPLICATE_HANDLE_CALLBACK
)(
170 PHANDLE_TABLE HandleTable
,
171 PHANDLE_TABLE_ENTRY HandleTableEntry
,
175 typedef BOOLEAN (STDCALL PEX_CHANGE_HANDLE_CALLBACK
)(
176 PHANDLE_TABLE HandleTable
,
177 PHANDLE_TABLE_ENTRY HandleTableEntry
,
182 ExpInitializeHandleTables(VOID
);
185 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL
);
188 ExDestroyHandleTable(
189 IN PHANDLE_TABLE HandleTable
194 IN PHANDLE_TABLE HandleTable
,
195 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL
,
196 IN PVOID Context OPTIONAL
201 IN PEPROCESS QuotaProcess OPTIONAL
,
202 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL
,
203 IN PVOID Context OPTIONAL
,
204 IN PHANDLE_TABLE SourceHandleTable
208 ExLockHandleTableEntry(
209 IN PHANDLE_TABLE HandleTable
,
210 IN PHANDLE_TABLE_ENTRY Entry
214 ExUnlockHandleTableEntry(
215 IN PHANDLE_TABLE HandleTable
,
216 IN PHANDLE_TABLE_ENTRY Entry
221 IN PHANDLE_TABLE HandleTable
,
222 IN PHANDLE_TABLE_ENTRY Entry
227 IN PHANDLE_TABLE HandleTable
,
232 ExDestroyHandleByEntry(
233 IN PHANDLE_TABLE HandleTable
,
234 IN PHANDLE_TABLE_ENTRY Entry
,
239 ExMapHandleToPointer(
240 IN PHANDLE_TABLE HandleTable
,
246 IN PHANDLE_TABLE HandleTable
,
248 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback
,
252 /* PSEH EXCEPTION HANDLING **************************************************/
256 ExSystemExceptionFilter(VOID
);
258 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
260 return ExSystemExceptionFilter();
263 /* RUNDOWN *******************************************************************/
266 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
267 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
269 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, y, z)
270 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
274 * @name ExfAcquireRundownProtection
277 * The ExfAcquireRundownProtection routine acquires rundown protection for
278 * the specified descriptor.
281 * Pointer to a rundown reference descriptor.
283 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
285 * @remarks This is the internal macro for system use only.In case the rundown
286 * was active, then the slow-path will be called through the exported
292 ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
294 ULONG_PTR Value
, NewValue
, OldValue
;
296 /* Get the current value and mask the active bit */
297 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
299 /* Add a reference */
300 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
302 /* Change the value */
303 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
304 if (OldValue
!= Value
)
306 /* Rundown was active, use long path */
307 return ExfAcquireRundownProtection(RunRef
);
315 * @name ExReleaseRundownProtection
318 * The ExReleaseRundownProtection routine releases rundown protection for
319 * the specified descriptor.
322 * Pointer to a rundown reference descriptor.
324 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
326 * @remarks This is the internal macro for system use only.In case the rundown
327 * was active, then the slow-path will be called through the exported
333 ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
335 ULONG_PTR Value
, NewValue
, OldValue
;
337 /* Get the current value and mask the active bit */
338 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
340 /* Remove a reference */
341 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
343 /* Change the value */
344 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
346 /* Check if the rundown was active */
347 if (OldValue
!= Value
)
349 /* Rundown was active, use long path */
350 ExfReleaseRundownProtection(RunRef
);
355 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
360 * @name ExInitializeRundownProtection
363 * The ExInitializeRundownProtection routine initializes a rundown
364 * protection descriptor.
367 * Pointer to a rundown reference descriptor.
371 * @remarks This is the internal macro for system use only.
376 ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
378 /* Set the count to zero */
383 * @name ExWaitForRundownProtectionRelease
386 * The ExWaitForRundownProtectionRelease routine waits until the specified
387 * rundown descriptor has been released.
390 * Pointer to a rundown reference descriptor.
394 * @remarks This is the internal macro for system use only. If a wait is actually
395 * necessary, then the slow path is taken through the exported function.
400 ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
404 /* Set the active bit */
405 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
406 if ((Value
) || (Value
!= EX_RUNDOWN_ACTIVE
))
408 /* If the the rundown wasn't already active, then take the long path */
409 ExfWaitForRundownProtectionRelease(RunRef
);
414 * @name ExRundownCompleted
417 * The ExRundownCompleted routine completes the rundown of the specified
418 * descriptor by setting the active bit.
421 * Pointer to a rundown reference descriptor.
425 * @remarks This is the internal macro for system use only.
430 ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
433 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
435 /* Mark the counter as active */
436 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
439 /* PUSHLOCKS *****************************************************************/
442 * @name ExAcquirePushLockExclusive
445 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
448 * Pointer to the pushlock which is to be acquired.
452 * @remarks The function attempts the quickest route to acquire the lock, which is
453 * to simply set the lock bit.
454 * However, if the pushlock is already shared, the slower path is taken.
456 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
457 * This macro should usually be paired up with KeAcquireCriticalRegion.
462 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
464 /* Try acquiring the lock */
465 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
467 /* Someone changed it, use the slow path */
468 ExfAcquirePushLockExclusive(PushLock
);
472 ASSERT(PushLock
->Locked
);
476 * @name ExAcquirePushLockShared
479 * The ExAcquirePushLockShared macro acquires a shared PushLock.
482 * Pointer to the pushlock which is to be acquired.
486 * @remarks The function attempts the quickest route to acquire the lock, which is
487 * to simply set the lock bit and set the share count to one.
488 * However, if the pushlock is already shared, the slower path is taken.
490 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
491 * This macro should usually be paired up with KeAcquireCriticalRegion.
496 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
498 EX_PUSH_LOCK NewValue
;
500 /* Try acquiring the lock */
501 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
502 if (!InterlockedCompareExchangePointer(PushLock
, NewValue
.Ptr
, 0))
504 /* Someone changed it, use the slow path */
505 ExfAcquirePushLockShared(PushLock
);
509 ASSERT(PushLock
->Locked
);
510 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
514 * @name ExWaitOnPushLock
517 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
520 * Pointer to a pushlock.
524 * @remarks The function attempts to get any exclusive waiters out of their slow
525 * path by forcing an instant acquire/release operation.
527 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
532 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
534 /* Acquire the lock */
535 ExfAcquirePushLockExclusive(PushLock
);
536 ASSERT(PushLock
->Locked
);
539 ExfReleasePushLockExclusive(PushLock
);
543 * @name ExReleasePushLockShared
546 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
549 * Pointer to a previously acquired pushlock.
553 * @remarks The function attempts the quickest route to release the lock, which is
554 * to simply decrease the share count and remove the lock bit.
555 * However, if the pushlock is being waited on then the long path is taken.
557 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
558 * This macro should usually be paired up with KeLeaveCriticalRegion.
563 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
565 EX_PUSH_LOCK OldValue
;
568 ASSERT(PushLock
->Locked
);
569 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
571 /* Try to clear the pushlock */
572 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
573 if (InterlockedCompareExchangePointer(PushLock
, 0, OldValue
.Ptr
) !=
576 /* There are still other people waiting on it */
577 ExfReleasePushLockShared(PushLock
);
582 * @name ExReleasePushLockExclusive
585 * The ExReleasePushLockExclusive macro releases a previously
586 * exclusively acquired PushLock.
589 * Pointer to a previously acquired pushlock.
593 * @remarks The function attempts the quickest route to release the lock, which is
594 * to simply clear the locked bit.
595 * However, if the pushlock is being waited on, the slow path is taken
596 * in an attempt to wake up the lock.
598 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
599 * This macro should usually be paired up with KeLeaveCriticalRegion.
604 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
606 EX_PUSH_LOCK OldValue
;
609 ASSERT(PushLock
->Locked
);
610 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
612 /* Unlock the pushlock */
613 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
, -1);
616 ASSERT(OldValue
.Locked
);
617 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
619 /* Check if anyone is waiting on it and it's not already waking*/
620 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
623 ExfTryToWakePushLock(PushLock
);
628 * @name ExReleasePushLock
631 * The ExReleasePushLock macro releases a previously acquired PushLock.
634 * Pointer to a previously acquired pushlock.
638 * @remarks The function attempts the quickest route to release the lock, which is
639 * to simply clear all the fields and decrease the share count if required.
640 * However, if the pushlock is being waited on then the long path is taken.
642 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
643 * This macro should usually be paired up with KeLeaveCriticalRegion.
648 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
650 EX_PUSH_LOCK OldValue
= *PushLock
;
651 EX_PUSH_LOCK NewValue
;
654 ASSERT(OldValue
.Locked
);
656 /* Check if the pushlock is shared */
657 if (OldValue
.Shared
> 1)
659 /* Decrease the share count */
660 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
664 /* Clear the pushlock entirely */
668 /* Check if nobody is waiting on us and try clearing the lock here */
669 if ((OldValue
.Waiting
) ||
670 (InterlockedCompareExchangePointer(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) ==
673 /* We have waiters, use the long path */
674 ExfReleasePushLock(PushLock
);
678 /* OTHER FUNCTIONS **********************************************************/
682 ExfpInterlockedExchange64(
683 LONGLONG
volatile * Destination
,
688 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
692 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
696 ExTimerRundown(VOID
);
698 #define InterlockedDecrementUL(Addend) \
699 (ULONG)InterlockedDecrement((PLONG)(Addend))
701 #define InterlockedIncrementUL(Addend) \
702 (ULONG)InterlockedIncrement((PLONG)(Addend))
704 #define InterlockedExchangeUL(Target, Value) \
705 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
707 #define InterlockedExchangeAddUL(Addend, Value) \
708 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
710 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
711 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
713 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
714 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
716 #define ExfpInterlockedExchange64UL(Target, Value) \
717 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
719 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */