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 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
20 #define ExAcquireResourceLock(l, i) \
21 UNREFERENCED_PARAMETER(*i); \
22 Ke386DisableInterrupts();
23 #define ExReleaseResourceLock(l, i) Ke386EnableInterrupts();
25 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
26 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
29 /* INITIALIZATION FUNCTIONS *************************************************/
41 ExpInitTimeZoneInfo(VOID
);
45 ExpInitializeWorkerThreads(VOID
);
49 ExpInitLookasideLists(VOID
);
53 ExpInitializeCallbacks(VOID
);
61 ExpInitializeExecutive(VOID
);
65 ExpInitializeEventImplementation(VOID
);
69 ExpInitializeEventImplementation(VOID
);
73 ExpInitializeEventPairImplementation(VOID
);
77 ExpInitializeSemaphoreImplementation(VOID
);
81 ExpInitializeMutantImplementation(VOID
);
85 ExpInitializeTimerImplementation(VOID
);
89 ExpInitializeProfileImplementation(VOID
);
93 ExpResourceInitialization(VOID
);
95 /* Rundown Functions ********************************************************/
99 ExfInitializeRundownProtection(
100 OUT PEX_RUNDOWN_REF RunRef
105 ExfReInitializeRundownProtection(
106 OUT PEX_RUNDOWN_REF RunRef
111 ExfAcquireRundownProtection(
112 IN OUT PEX_RUNDOWN_REF RunRef
117 ExfAcquireRundownProtectionEx(
118 IN OUT PEX_RUNDOWN_REF RunRef
,
124 ExfReleaseRundownProtection(
125 IN OUT PEX_RUNDOWN_REF RunRef
130 ExfReleaseRundownProtectionEx(
131 IN OUT PEX_RUNDOWN_REF RunRef
,
138 OUT PEX_RUNDOWN_REF RunRef
143 ExfWaitForRundownProtectionRelease(
144 IN OUT PEX_RUNDOWN_REF RunRef
147 /* HANDLE TABLE FUNCTIONS ***************************************************/
149 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
150 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
151 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
152 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
154 #define EX_HANDLE_TABLE_CLOSING 0x1
156 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
157 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
158 EX_HANDLE_ENTRY_INHERITABLE | \
159 EX_HANDLE_ENTRY_AUDITONCLOSE)
161 typedef VOID (STDCALL PEX_SWEEP_HANDLE_CALLBACK
)(
162 PHANDLE_TABLE HandleTable
,
168 typedef BOOLEAN (STDCALL PEX_DUPLICATE_HANDLE_CALLBACK
)(
169 PHANDLE_TABLE HandleTable
,
170 PHANDLE_TABLE_ENTRY HandleTableEntry
,
174 typedef BOOLEAN (STDCALL PEX_CHANGE_HANDLE_CALLBACK
)(
175 PHANDLE_TABLE HandleTable
,
176 PHANDLE_TABLE_ENTRY HandleTableEntry
,
181 ExpInitializeHandleTables(VOID
);
184 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL
);
187 ExDestroyHandleTable(
188 IN PHANDLE_TABLE HandleTable
193 IN PHANDLE_TABLE HandleTable
,
194 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL
,
195 IN PVOID Context OPTIONAL
200 IN PEPROCESS QuotaProcess OPTIONAL
,
201 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL
,
202 IN PVOID Context OPTIONAL
,
203 IN PHANDLE_TABLE SourceHandleTable
207 ExLockHandleTableEntry(
208 IN PHANDLE_TABLE HandleTable
,
209 IN PHANDLE_TABLE_ENTRY Entry
213 ExUnlockHandleTableEntry(
214 IN PHANDLE_TABLE HandleTable
,
215 IN PHANDLE_TABLE_ENTRY Entry
220 IN PHANDLE_TABLE HandleTable
,
221 IN PHANDLE_TABLE_ENTRY Entry
226 IN PHANDLE_TABLE HandleTable
,
231 ExDestroyHandleByEntry(
232 IN PHANDLE_TABLE HandleTable
,
233 IN PHANDLE_TABLE_ENTRY Entry
,
238 ExMapHandleToPointer(
239 IN PHANDLE_TABLE HandleTable
,
245 IN PHANDLE_TABLE HandleTable
,
247 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback
,
251 /* PSEH EXCEPTION HANDLING **************************************************/
255 ExSystemExceptionFilter(VOID
);
257 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
259 return ExSystemExceptionFilter();
262 /* RUNDOWN *******************************************************************/
265 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
266 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
268 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, y, z)
269 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
273 * @name ExfAcquireRundownProtection
276 * The ExfAcquireRundownProtection routine acquires rundown protection for
277 * the specified descriptor.
280 * Pointer to a rundown reference descriptor.
282 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
284 * @remarks This is the internal macro for system use only.In case the rundown
285 * was active, then the slow-path will be called through the exported
291 ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
293 ULONG_PTR Value
, NewValue
, OldValue
;
295 /* Get the current value and mask the active bit */
296 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
298 /* Add a reference */
299 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
301 /* Change the value */
302 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
303 if (OldValue
!= Value
)
305 /* Rundown was active, use long path */
306 return ExfAcquireRundownProtection(RunRef
);
314 * @name ExReleaseRundownProtection
317 * The ExReleaseRundownProtection routine releases rundown protection for
318 * the specified descriptor.
321 * Pointer to a rundown reference descriptor.
323 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
325 * @remarks This is the internal macro for system use only.In case the rundown
326 * was active, then the slow-path will be called through the exported
332 ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
334 ULONG_PTR Value
, NewValue
, OldValue
;
336 /* Get the current value and mask the active bit */
337 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
339 /* Remove a reference */
340 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
342 /* Change the value */
343 OldValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
345 /* Check if the rundown was active */
346 if (OldValue
!= Value
)
348 /* Rundown was active, use long path */
349 ExfReleaseRundownProtection(RunRef
);
354 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
359 * @name ExInitializeRundownProtection
362 * The ExInitializeRundownProtection routine initializes a rundown
363 * protection descriptor.
366 * Pointer to a rundown reference descriptor.
370 * @remarks This is the internal macro for system use only.
375 ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
377 /* Set the count to zero */
382 * @name ExWaitForRundownProtectionRelease
385 * The ExWaitForRundownProtectionRelease routine waits until the specified
386 * rundown descriptor has been released.
389 * Pointer to a rundown reference descriptor.
393 * @remarks This is the internal macro for system use only. If a wait is actually
394 * necessary, then the slow path is taken through the exported function.
399 ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
403 /* Set the active bit */
404 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
405 if ((Value
) || (Value
!= EX_RUNDOWN_ACTIVE
))
407 /* If the the rundown wasn't already active, then take the long path */
408 ExfWaitForRundownProtectionRelease(RunRef
);
413 * @name ExRundownCompleted
416 * The ExRundownCompleted routine completes the rundown of the specified
417 * descriptor by setting the active bit.
420 * Pointer to a rundown reference descriptor.
424 * @remarks This is the internal macro for system use only.
429 ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
432 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
434 /* Mark the counter as active */
435 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
438 /* PUSHLOCKS *****************************************************************/
441 * @name ExAcquirePushLockExclusive
444 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
447 * Pointer to the pushlock which is to be acquired.
451 * @remarks The function attempts the quickest route to acquire the lock, which is
452 * to simply set the lock bit.
453 * However, if the pushlock is already shared, the slower path is taken.
455 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
456 * This macro should usually be paired up with KeAcquireCriticalRegion.
461 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
463 /* Try acquiring the lock */
464 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
466 /* Someone changed it, use the slow path */
467 ExfAcquirePushLockExclusive(PushLock
);
471 ASSERT(PushLock
->Locked
);
475 * @name ExAcquirePushLockShared
478 * The ExAcquirePushLockShared macro acquires a shared PushLock.
481 * Pointer to the pushlock which is to be acquired.
485 * @remarks The function attempts the quickest route to acquire the lock, which is
486 * to simply set the lock bit and set the share count to one.
487 * However, if the pushlock is already shared, the slower path is taken.
489 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
490 * This macro should usually be paired up with KeAcquireCriticalRegion.
495 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
497 EX_PUSH_LOCK NewValue
;
499 /* Try acquiring the lock */
500 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
501 if (!InterlockedCompareExchangePointer(PushLock
, NewValue
.Ptr
, 0))
503 /* Someone changed it, use the slow path */
504 ExfAcquirePushLockShared(PushLock
);
508 ASSERT(PushLock
->Locked
);
509 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
513 * @name ExWaitOnPushLock
516 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
519 * Pointer to a pushlock.
523 * @remarks The function attempts to get any exclusive waiters out of their slow
524 * path by forcing an instant acquire/release operation.
526 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
531 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
533 /* Acquire the lock */
534 ExfAcquirePushLockExclusive(PushLock
);
535 ASSERT(PushLock
->Locked
);
538 ExfReleasePushLockExclusive(PushLock
);
542 * @name ExReleasePushLockShared
545 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
548 * Pointer to a previously acquired pushlock.
552 * @remarks The function attempts the quickest route to release the lock, which is
553 * to simply decrease the share count and remove the lock bit.
554 * However, if the pushlock is being waited on then the long path is taken.
556 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
557 * This macro should usually be paired up with KeLeaveCriticalRegion.
562 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
564 EX_PUSH_LOCK OldValue
;
567 ASSERT(PushLock
->Locked
);
568 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
570 /* Try to clear the pushlock */
571 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
572 if (InterlockedCompareExchangePointer(PushLock
, 0, OldValue
.Ptr
) !=
575 /* There are still other people waiting on it */
576 ExfReleasePushLockShared(PushLock
);
581 * @name ExReleasePushLockExclusive
584 * The ExReleasePushLockExclusive macro releases a previously
585 * exclusively acquired PushLock.
588 * Pointer to a previously acquired pushlock.
592 * @remarks The function attempts the quickest route to release the lock, which is
593 * to simply clear the locked bit.
594 * However, if the pushlock is being waited on, the slow path is taken
595 * in an attempt to wake up the lock.
597 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
598 * This macro should usually be paired up with KeLeaveCriticalRegion.
603 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
605 EX_PUSH_LOCK OldValue
;
608 ASSERT(PushLock
->Locked
);
609 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
611 /* Unlock the pushlock */
612 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
, -1);
615 ASSERT(OldValue
.Locked
);
616 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
618 /* Check if anyone is waiting on it and it's not already waking*/
619 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
622 ExfTryToWakePushLock(PushLock
);
627 * @name ExReleasePushLock
630 * The ExReleasePushLock macro releases a previously acquired PushLock.
633 * Pointer to a previously acquired pushlock.
637 * @remarks The function attempts the quickest route to release the lock, which is
638 * to simply clear all the fields and decrease the share count if required.
639 * However, if the pushlock is being waited on then the long path is taken.
641 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
642 * This macro should usually be paired up with KeLeaveCriticalRegion.
647 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
649 EX_PUSH_LOCK OldValue
= *PushLock
;
650 EX_PUSH_LOCK NewValue
;
653 ASSERT(OldValue
.Locked
);
655 /* Check if the pushlock is shared */
656 if (OldValue
.Shared
> 1)
658 /* Decrease the share count */
659 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
663 /* Clear the pushlock entirely */
667 /* Check if nobody is waiting on us and try clearing the lock here */
668 if ((OldValue
.Waiting
) ||
669 (InterlockedCompareExchangePointer(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) ==
672 /* We have waiters, use the long path */
673 ExfReleasePushLock(PushLock
);
677 /* OTHER FUNCTIONS **********************************************************/
681 ExfpInterlockedExchange64(
682 LONGLONG
volatile * Destination
,
687 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
691 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
695 ExTimerRundown(VOID
);
697 #define InterlockedDecrementUL(Addend) \
698 (ULONG)InterlockedDecrement((PLONG)(Addend))
700 #define InterlockedIncrementUL(Addend) \
701 (ULONG)InterlockedIncrement((PLONG)(Addend))
703 #define InterlockedExchangeUL(Target, Value) \
704 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
706 #define InterlockedExchangeAddUL(Addend, Value) \
707 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
709 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
710 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
712 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
713 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
715 #define ExfpInterlockedExchange64UL(Target, Value) \
716 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
718 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */