bcf3471dbafafc53d172fa507fc96005489cd803
[reactos.git] / reactos / ntoskrnl / include / internal / ex.h
1 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H
2 #define __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H
3
4 /* GLOBAL VARIABLES *********************************************************/
5
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;
23
24 #define MAX_FAST_REFS 7
25
26 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
27 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
28 EX_HANDLE_ENTRY_AUDITONCLOSE)))
29 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->Object) & \
30 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
31 EX_HANDLE_ENTRY_AUDITONCLOSE)))
32
33 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
34 #ifndef CONFIG_SMP
35 #define ExAcquireResourceLock(l, i) { \
36 (void)i; \
37 _disable(); \
38 }
39 #define ExReleaseResourceLock(l, i) _enable();
40 #else
41 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
42 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
43 #endif
44
45 #define ExAcquireRundownProtection _ExAcquireRundownProtection
46 #define ExReleaseRundownProtection _ExReleaseRundownProtection
47 #define ExInitializeRundownProtection _ExInitializeRundownProtection
48 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
49 #define ExRundownCompleted _ExRundownCompleted
50 #define ExGetPreviousMode KeGetPreviousMode
51
52 /* INITIALIZATION FUNCTIONS *************************************************/
53
54 VOID
55 NTAPI
56 ExpWin32kInit(VOID);
57
58 VOID
59 NTAPI
60 ExInit2(VOID);
61
62 VOID
63 NTAPI
64 ExPhase2Init(
65 IN PVOID Context
66 );
67
68 VOID
69 NTAPI
70 ExpInitializePushLocks(VOID);
71
72 BOOLEAN
73 NTAPI
74 ExRefreshTimeZoneInformation(
75 IN PLARGE_INTEGER SystemBootTime
76 );
77
78 VOID
79 NTAPI
80 ExpInitializeWorkerThreads(VOID);
81
82 VOID
83 NTAPI
84 ExpInitLookasideLists(VOID);
85
86 VOID
87 NTAPI
88 ExInitializeSystemLookasideList(
89 IN PGENERAL_LOOKASIDE List,
90 IN POOL_TYPE Type,
91 IN ULONG Size,
92 IN ULONG Tag,
93 IN USHORT MaximumDepth,
94 IN PLIST_ENTRY ListHead
95 );
96
97 VOID
98 NTAPI
99 ExpInitializeCallbacks(VOID);
100
101 VOID
102 NTAPI
103 ExpInitUuids(VOID);
104
105 VOID
106 NTAPI
107 ExpInitializeExecutive(
108 IN ULONG Cpu,
109 IN PLOADER_PARAMETER_BLOCK LoaderBlock
110 );
111
112 VOID
113 NTAPI
114 ExpInitializeEventImplementation(VOID);
115
116 VOID
117 NTAPI
118 ExpInitializeEventImplementation(VOID);
119
120 VOID
121 NTAPI
122 ExpInitializeEventPairImplementation(VOID);
123
124 VOID
125 NTAPI
126 ExpInitializeSemaphoreImplementation(VOID);
127
128 VOID
129 NTAPI
130 ExpInitializeMutantImplementation(VOID);
131
132 VOID
133 NTAPI
134 ExpInitializeTimerImplementation(VOID);
135
136 VOID
137 NTAPI
138 ExpInitializeProfileImplementation(VOID);
139
140 VOID
141 NTAPI
142 ExpResourceInitialization(VOID);
143
144 VOID
145 NTAPI
146 ExInitPoolLookasidePointers(VOID);
147
148 /* Callback Functions ********************************************************/
149
150 VOID
151 NTAPI
152 ExInitializeCallBack(
153 IN PEX_CALLBACK Callback
154 );
155
156 /* Rundown Functions ********************************************************/
157
158 VOID
159 FASTCALL
160 ExfInitializeRundownProtection(
161 OUT PEX_RUNDOWN_REF RunRef
162 );
163
164 VOID
165 FASTCALL
166 ExfReInitializeRundownProtection(
167 OUT PEX_RUNDOWN_REF RunRef
168 );
169
170 BOOLEAN
171 FASTCALL
172 ExfAcquireRundownProtection(
173 IN OUT PEX_RUNDOWN_REF RunRef
174 );
175
176 BOOLEAN
177 FASTCALL
178 ExfAcquireRundownProtectionEx(
179 IN OUT PEX_RUNDOWN_REF RunRef,
180 IN ULONG Count
181 );
182
183 VOID
184 FASTCALL
185 ExfReleaseRundownProtection(
186 IN OUT PEX_RUNDOWN_REF RunRef
187 );
188
189 VOID
190 FASTCALL
191 ExfReleaseRundownProtectionEx(
192 IN OUT PEX_RUNDOWN_REF RunRef,
193 IN ULONG Count
194 );
195
196 VOID
197 FASTCALL
198 ExfRundownCompleted(
199 OUT PEX_RUNDOWN_REF RunRef
200 );
201
202 VOID
203 FASTCALL
204 ExfWaitForRundownProtectionRelease(
205 IN OUT PEX_RUNDOWN_REF RunRef
206 );
207
208 /* HANDLE TABLE FUNCTIONS ***************************************************/
209
210 #define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
211 #define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
212 #define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
213 #define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
214
215 #define EX_HANDLE_TABLE_CLOSING 0x1
216
217 #define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
218 EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
219 EX_HANDLE_ENTRY_INHERITABLE | \
220 EX_HANDLE_ENTRY_AUDITONCLOSE)
221
222 typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK)(
223 PHANDLE_TABLE_ENTRY HandleTableEntry,
224 HANDLE Handle,
225 PVOID Context
226 );
227
228 typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK)(
229 PHANDLE_TABLE HandleTable,
230 PHANDLE_TABLE_ENTRY HandleTableEntry,
231 PVOID Context
232 );
233
234 typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK)(
235 PHANDLE_TABLE HandleTable,
236 PHANDLE_TABLE_ENTRY HandleTableEntry,
237 PVOID Context
238 );
239
240 VOID
241 ExpInitializeHandleTables(VOID);
242
243 PHANDLE_TABLE
244 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL);
245
246 VOID
247 ExDestroyHandleTable(
248 IN PHANDLE_TABLE HandleTable
249 );
250
251 VOID
252 ExSweepHandleTable(
253 IN PHANDLE_TABLE HandleTable,
254 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL,
255 IN PVOID Context OPTIONAL
256 );
257
258 PHANDLE_TABLE
259 ExDupHandleTable(
260 IN PEPROCESS QuotaProcess OPTIONAL,
261 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL,
262 IN PVOID Context OPTIONAL,
263 IN PHANDLE_TABLE SourceHandleTable
264 );
265
266 BOOLEAN
267 ExLockHandleTableEntry(
268 IN PHANDLE_TABLE HandleTable,
269 IN PHANDLE_TABLE_ENTRY Entry
270 );
271
272 VOID
273 ExUnlockHandleTableEntry(
274 IN PHANDLE_TABLE HandleTable,
275 IN PHANDLE_TABLE_ENTRY Entry
276 );
277
278 HANDLE
279 ExCreateHandle(
280 IN PHANDLE_TABLE HandleTable,
281 IN PHANDLE_TABLE_ENTRY Entry
282 );
283
284 BOOLEAN
285 ExDestroyHandle(
286 IN PHANDLE_TABLE HandleTable,
287 IN HANDLE Handle
288 );
289
290 VOID
291 ExDestroyHandleByEntry(
292 IN PHANDLE_TABLE HandleTable,
293 IN PHANDLE_TABLE_ENTRY Entry,
294 IN HANDLE Handle
295 );
296
297 PHANDLE_TABLE_ENTRY
298 ExMapHandleToPointer(
299 IN PHANDLE_TABLE HandleTable,
300 IN HANDLE Handle
301 );
302
303 BOOLEAN
304 ExChangeHandle(
305 IN PHANDLE_TABLE HandleTable,
306 IN HANDLE Handle,
307 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
308 IN PVOID Context
309 );
310
311 /* PSEH EXCEPTION HANDLING **************************************************/
312
313 LONG
314 NTAPI
315 ExSystemExceptionFilter(VOID);
316
317 static __inline _SEH_FILTER(_SEH_ExSystemExceptionFilter)
318 {
319 return ExSystemExceptionFilter();
320 }
321
322 /* RUNDOWN *******************************************************************/
323
324 #ifdef _WIN64
325 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
326 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
327 #else
328 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
329 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
330 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
331 #endif
332
333 /*++
334 * @name ExfAcquireRundownProtection
335 * INTERNAL MACRO
336 *
337 * The ExfAcquireRundownProtection routine acquires rundown protection for
338 * the specified descriptor.
339 *
340 * @param RunRef
341 * Pointer to a rundown reference descriptor.
342 *
343 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
344 *
345 * @remarks This is the internal macro for system use only.In case the rundown
346 * was active, then the slow-path will be called through the exported
347 * function.
348 *
349 *--*/
350 BOOLEAN
351 FORCEINLINE
352 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
353 {
354 ULONG_PTR Value, NewValue;
355
356 /* Get the current value and mask the active bit */
357 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
358
359 /* Add a reference */
360 NewValue = Value + EX_RUNDOWN_COUNT_INC;
361
362 /* Change the value */
363 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
364 if (NewValue != Value)
365 {
366 /* Rundown was active, use long path */
367 return ExfAcquireRundownProtection(RunRef);
368 }
369
370 /* Success */
371 return TRUE;
372 }
373
374 /*++
375 * @name ExReleaseRundownProtection
376 * INTERNAL MACRO
377 *
378 * The ExReleaseRundownProtection routine releases rundown protection for
379 * the specified descriptor.
380 *
381 * @param RunRef
382 * Pointer to a rundown reference descriptor.
383 *
384 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
385 *
386 * @remarks This is the internal macro for system use only.In case the rundown
387 * was active, then the slow-path will be called through the exported
388 * function.
389 *
390 *--*/
391 VOID
392 FORCEINLINE
393 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
394 {
395 ULONG_PTR Value, NewValue;
396
397 /* Get the current value and mask the active bit */
398 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
399
400 /* Remove a reference */
401 NewValue = Value - EX_RUNDOWN_COUNT_INC;
402
403 /* Change the value */
404 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
405
406 /* Check if the rundown was active */
407 if (NewValue != Value)
408 {
409 /* Rundown was active, use long path */
410 ExfReleaseRundownProtection(RunRef);
411 }
412 else
413 {
414 /* Sanity check */
415 ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
416 }
417 }
418
419 /*++
420 * @name ExInitializeRundownProtection
421 * INTERNAL MACRO
422 *
423 * The ExInitializeRundownProtection routine initializes a rundown
424 * protection descriptor.
425 *
426 * @param RunRef
427 * Pointer to a rundown reference descriptor.
428 *
429 * @return None.
430 *
431 * @remarks This is the internal macro for system use only.
432 *
433 *--*/
434 VOID
435 FORCEINLINE
436 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
437 {
438 /* Set the count to zero */
439 RunRef->Count = 0;
440 }
441
442 /*++
443 * @name ExWaitForRundownProtectionRelease
444 * INTERNAL MACRO
445 *
446 * The ExWaitForRundownProtectionRelease routine waits until the specified
447 * rundown descriptor has been released.
448 *
449 * @param RunRef
450 * Pointer to a rundown reference descriptor.
451 *
452 * @return None.
453 *
454 * @remarks This is the internal macro for system use only. If a wait is actually
455 * necessary, then the slow path is taken through the exported function.
456 *
457 *--*/
458 VOID
459 FORCEINLINE
460 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
461 {
462 ULONG_PTR Value;
463
464 /* Set the active bit */
465 Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
466 if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
467 {
468 /* If the the rundown wasn't already active, then take the long path */
469 ExfWaitForRundownProtectionRelease(RunRef);
470 }
471 }
472
473 /*++
474 * @name ExRundownCompleted
475 * INTERNAL MACRO
476 *
477 * The ExRundownCompleted routine completes the rundown of the specified
478 * descriptor by setting the active bit.
479 *
480 * @param RunRef
481 * Pointer to a rundown reference descriptor.
482 *
483 * @return None.
484 *
485 * @remarks This is the internal macro for system use only.
486 *
487 *--*/
488 VOID
489 FORCEINLINE
490 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
491 {
492 /* Sanity check */
493 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
494
495 /* Mark the counter as active */
496 ExpSetRundown(&RunRef->Count, EX_RUNDOWN_ACTIVE);
497 }
498
499 /* PUSHLOCKS *****************************************************************/
500
501 /*++
502 * @name ExInitializePushLock
503 * INTERNAL MACRO
504 *
505 * The ExInitializePushLock macro initializes a PushLock.
506 *
507 * @params PushLock
508 * Pointer to the pushlock which is to be initialized.
509 *
510 * @return None.
511 *
512 * @remarks None.
513 *
514 *--*/
515 VOID
516 FORCEINLINE
517 ExInitializePushLock(IN PULONG_PTR PushLock)
518 {
519 /* Set the value to 0 */
520 *PushLock = 0;
521 }
522
523 /*++
524 * @name ExAcquirePushLockExclusive
525 * INTERNAL MACRO
526 *
527 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
528 *
529 * @params PushLock
530 * Pointer to the pushlock which is to be acquired.
531 *
532 * @return None.
533 *
534 * @remarks The function attempts the quickest route to acquire the lock, which is
535 * to simply set the lock bit.
536 * However, if the pushlock is already shared, the slower path is taken.
537 *
538 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
539 * This macro should usually be paired up with KeAcquireCriticalRegion.
540 *
541 *--*/
542 VOID
543 FORCEINLINE
544 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
545 {
546 /* Try acquiring the lock */
547 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
548 {
549 /* Someone changed it, use the slow path */
550 DbgPrint("%s - Contention!\n", __FUNCTION__);
551 ExfAcquirePushLockExclusive(PushLock);
552 }
553
554 /* Sanity check */
555 ASSERT(PushLock->Locked);
556 }
557
558 /*++
559 * @name ExAcquirePushLockShared
560 * INTERNAL MACRO
561 *
562 * The ExAcquirePushLockShared macro acquires a shared PushLock.
563 *
564 * @params PushLock
565 * Pointer to the pushlock which is to be acquired.
566 *
567 * @return None.
568 *
569 * @remarks The function attempts the quickest route to acquire the lock, which is
570 * to simply set the lock bit and set the share count to one.
571 * However, if the pushlock is already shared, the slower path is taken.
572 *
573 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
574 * This macro should usually be paired up with KeAcquireCriticalRegion.
575 *
576 *--*/
577 VOID
578 FORCEINLINE
579 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
580 {
581 EX_PUSH_LOCK NewValue;
582
583 /* Try acquiring the lock */
584 NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
585 if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
586 {
587 /* Someone changed it, use the slow path */
588 DbgPrint("%s - Contention!\n", __FUNCTION__);
589 ExfAcquirePushLockShared(PushLock);
590 }
591
592 /* Sanity checks */
593 ASSERT(PushLock->Locked);
594 ASSERT(PushLock->Waiting || PushLock->Shared > 0);
595 }
596
597 /*++
598 * @name ExConvertPushLockSharedToExclusive
599 * INTERNAL MACRO
600 *
601 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
602 * pushlock to a shared pushlock.
603 *
604 * @params PushLock
605 * Pointer to the pushlock which is to be converted.
606 *
607 * @return FALSE if conversion failed, TRUE otherwise.
608 *
609 * @remarks The function attempts the quickest route to convert the lock, which is
610 * to simply set the lock bit and remove any other bits.
611 *
612 *--*/
613 BOOLEAN
614 FORCEINLINE
615 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
616 {
617 EX_PUSH_LOCK OldValue;
618
619 /* Set the expected old value */
620 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
621
622 /* Try converting the lock */
623 if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) !=
624 OldValue.Ptr)
625 {
626 /* Conversion failed */
627 return FALSE;
628 }
629
630 /* Sanity check */
631 ASSERT(PushLock->Locked);
632 return TRUE;
633 }
634
635 /*++
636 * @name ExWaitOnPushLock
637 * INTERNAL MACRO
638 *
639 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
640 *
641 * @params PushLock
642 * Pointer to a pushlock.
643 *
644 * @return None.
645 *
646 * @remarks The function attempts to get any exclusive waiters out of their slow
647 * path by forcing an instant acquire/release operation.
648 *
649 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
650 *
651 *--*/
652 VOID
653 FORCEINLINE
654 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
655 {
656 /* Acquire the lock */
657 ExfAcquirePushLockExclusive(PushLock);
658 ASSERT(PushLock->Locked);
659
660 /* Release it */
661 ExfReleasePushLockExclusive(PushLock);
662 }
663
664 /*++
665 * @name ExReleasePushLockShared
666 * INTERNAL MACRO
667 *
668 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
669 *
670 * @params PushLock
671 * Pointer to a previously acquired pushlock.
672 *
673 * @return None.
674 *
675 * @remarks The function attempts the quickest route to release the lock, which is
676 * to simply decrease the share count and remove the lock bit.
677 * However, if the pushlock is being waited on then the long path is taken.
678 *
679 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
680 * This macro should usually be paired up with KeLeaveCriticalRegion.
681 *
682 *--*/
683 VOID
684 FORCEINLINE
685 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
686 {
687 EX_PUSH_LOCK OldValue;
688
689 /* Sanity checks */
690 ASSERT(PushLock->Locked);
691 ASSERT(PushLock->Waiting || PushLock->Shared > 0);
692
693 /* Try to clear the pushlock */
694 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
695 if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr)
696 {
697 /* There are still other people waiting on it */
698 DbgPrint("%s - Contention!\n", __FUNCTION__);
699 ExfReleasePushLockShared(PushLock);
700 }
701 }
702
703 /*++
704 * @name ExReleasePushLockExclusive
705 * INTERNAL MACRO
706 *
707 * The ExReleasePushLockExclusive macro releases a previously
708 * exclusively acquired PushLock.
709 *
710 * @params PushLock
711 * Pointer to a previously acquired pushlock.
712 *
713 * @return None.
714 *
715 * @remarks The function attempts the quickest route to release the lock, which is
716 * to simply clear the locked bit.
717 * However, if the pushlock is being waited on, the slow path is taken
718 * in an attempt to wake up the lock.
719 *
720 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
721 * This macro should usually be paired up with KeLeaveCriticalRegion.
722 *
723 *--*/
724 VOID
725 FORCEINLINE
726 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
727 {
728 EX_PUSH_LOCK OldValue;
729
730 /* Sanity checks */
731 ASSERT(PushLock->Locked);
732 ASSERT(PushLock->Waiting || PushLock->Shared == 0);
733
734 /* Unlock the pushlock */
735 OldValue.Value = InterlockedExchangeAddSizeT((PLONG)PushLock,
736 -EX_PUSH_LOCK_LOCK);
737
738 /* Sanity checks */
739 ASSERT(OldValue.Locked);
740 ASSERT(OldValue.Waiting || OldValue.Shared == 0);
741
742 /* Check if anyone is waiting on it and it's not already waking*/
743 if ((OldValue.Waiting) && !(OldValue.Waking))
744 {
745 /* Wake it up */
746 DbgPrint("%s - Contention!\n", __FUNCTION__);
747 ExfTryToWakePushLock(PushLock);
748 }
749 }
750
751 /*++
752 * @name ExReleasePushLock
753 * INTERNAL MACRO
754 *
755 * The ExReleasePushLock macro releases a previously acquired PushLock.
756 *
757 * @params PushLock
758 * Pointer to a previously acquired pushlock.
759 *
760 * @return None.
761 *
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.
765 *
766 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
767 * This macro should usually be paired up with KeLeaveCriticalRegion.
768 *
769 *--*/
770 VOID
771 FORCEINLINE
772 ExReleasePushLock(PEX_PUSH_LOCK PushLock)
773 {
774 EX_PUSH_LOCK OldValue = *PushLock;
775 EX_PUSH_LOCK NewValue;
776
777 /* Sanity checks */
778 ASSERT(OldValue.Locked);
779
780 /* Check if the pushlock is shared */
781 if (OldValue.Shared > 1)
782 {
783 /* Decrease the share count */
784 NewValue.Value = OldValue.Value &~ EX_PUSH_LOCK_SHARE_INC;
785 }
786 else
787 {
788 /* Clear the pushlock entirely */
789 NewValue.Value = 0;
790 }
791
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) !=
795 OldValue.Ptr))
796 {
797 /* We have waiters, use the long path */
798 DbgPrint("%s - Contention!\n", __FUNCTION__);
799 ExfReleasePushLock(PushLock);
800 }
801 }
802
803 /* OTHER FUNCTIONS **********************************************************/
804
805 LONGLONG
806 FASTCALL
807 ExfpInterlockedExchange64(
808 LONGLONG volatile * Destination,
809 PLONGLONG Exchange
810 );
811
812 NTSTATUS
813 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation);
814
815 NTSTATUS
816 NTAPI
817 ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId);
818
819 VOID
820 NTAPI
821 ExTimerRundown(VOID);
822
823 #define InterlockedDecrementUL(Addend) \
824 (ULONG)InterlockedDecrement((PLONG)(Addend))
825
826 #define InterlockedIncrementUL(Addend) \
827 (ULONG)InterlockedIncrement((PLONG)(Addend))
828
829 #define InterlockedExchangeUL(Target, Value) \
830 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
831
832 #define InterlockedExchangeAddUL(Addend, Value) \
833 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
834
835 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
836 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
837
838 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
839 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
840
841 #define ExfpInterlockedExchange64UL(Target, Value) \
842 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
843
844 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */