Partially fixed up tree after merge from HEAD. More to do.
[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 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;
21
22 #define MAX_FAST_REFS 7
23
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)))
30
31 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
32 #ifdef _M_IX86
33 #ifndef CONFIG_SMP
34 #define ExAcquireResourceLock(l, i) { \
35 (void)i; \
36 Ke386DisableInterrupts(); \
37 }
38 #define ExReleaseResourceLock(l, i) Ke386EnableInterrupts();
39 #else
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 */
44 /* XXX arty fixme */
45 #define ExAcquireResourceLock(l,i) KeAcquireSpinLock(l,i);
46 #define ExReleaseResourceLock(l,i) KeReleaseSpinLock(l,i);
47 #endif
48
49 #define ExAcquireRundownProtection _ExAcquireRundownProtection
50 #define ExReleaseRundownProtection _ExReleaseRundownProtection
51 #define ExInitializeRundownProtection _ExInitializeRundownProtection
52 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
53 #define ExRundownCompleted _ExRundownCompleted
54
55 /* INITIALIZATION FUNCTIONS *************************************************/
56
57 VOID
58 NTAPI
59 ExpWin32kInit(VOID);
60
61 VOID
62 NTAPI
63 ExInit2(VOID);
64
65 VOID
66 NTAPI
67 ExPhase2Init(
68 IN PVOID Context
69 );
70
71 VOID
72 NTAPI
73 ExpInitializePushLocks(VOID);
74
75 VOID
76 NTAPI
77 ExpInitTimeZoneInfo(VOID);
78
79 VOID
80 NTAPI
81 ExpInitializeWorkerThreads(VOID);
82
83 VOID
84 NTAPI
85 ExpInitLookasideLists(VOID);
86
87 VOID
88 NTAPI
89 ExInitializeSystemLookasideList(
90 IN PGENERAL_LOOKASIDE List,
91 IN POOL_TYPE Type,
92 IN ULONG Size,
93 IN ULONG Tag,
94 IN USHORT MaximumDepth,
95 IN PLIST_ENTRY ListHead
96 );
97
98 VOID
99 NTAPI
100 ExpInitializeCallbacks(VOID);
101
102 VOID
103 NTAPI
104 ExpInitUuids(VOID);
105
106 VOID
107 NTAPI
108 ExpInitializeExecutive(
109 IN ULONG Cpu,
110 IN PLOADER_PARAMETER_BLOCK LoaderBlock
111 );
112
113 VOID
114 NTAPI
115 ExpInitializeEventImplementation(VOID);
116
117 VOID
118 NTAPI
119 ExpInitializeEventImplementation(VOID);
120
121 VOID
122 NTAPI
123 ExpInitializeEventPairImplementation(VOID);
124
125 VOID
126 NTAPI
127 ExpInitializeSemaphoreImplementation(VOID);
128
129 VOID
130 NTAPI
131 ExpInitializeMutantImplementation(VOID);
132
133 VOID
134 NTAPI
135 ExpInitializeTimerImplementation(VOID);
136
137 VOID
138 NTAPI
139 ExpInitializeProfileImplementation(VOID);
140
141 VOID
142 NTAPI
143 ExpResourceInitialization(VOID);
144
145 VOID
146 NTAPI
147 ExInitPoolLookasidePointers(VOID);
148
149 /* Callback Functions ********************************************************/
150
151 VOID
152 NTAPI
153 ExInitializeCallBack(
154 IN PEX_CALLBACK Callback
155 );
156
157 /* Rundown Functions ********************************************************/
158
159 VOID
160 FASTCALL
161 ExfInitializeRundownProtection(
162 OUT PEX_RUNDOWN_REF RunRef
163 );
164
165 VOID
166 FASTCALL
167 ExfReInitializeRundownProtection(
168 OUT PEX_RUNDOWN_REF RunRef
169 );
170
171 BOOLEAN
172 FASTCALL
173 ExfAcquireRundownProtection(
174 IN OUT PEX_RUNDOWN_REF RunRef
175 );
176
177 BOOLEAN
178 FASTCALL
179 ExfAcquireRundownProtectionEx(
180 IN OUT PEX_RUNDOWN_REF RunRef,
181 IN ULONG Count
182 );
183
184 VOID
185 FASTCALL
186 ExfReleaseRundownProtection(
187 IN OUT PEX_RUNDOWN_REF RunRef
188 );
189
190 VOID
191 FASTCALL
192 ExfReleaseRundownProtectionEx(
193 IN OUT PEX_RUNDOWN_REF RunRef,
194 IN ULONG Count
195 );
196
197 VOID
198 FASTCALL
199 ExfRundownCompleted(
200 OUT PEX_RUNDOWN_REF RunRef
201 );
202
203 VOID
204 FASTCALL
205 ExfWaitForRundownProtectionRelease(
206 IN OUT PEX_RUNDOWN_REF RunRef
207 );
208
209 /* HANDLE TABLE FUNCTIONS ***************************************************/
210
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)
215
216 #define EX_HANDLE_TABLE_CLOSING 0x1
217
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)
222
223 typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK)(
224 PHANDLE_TABLE_ENTRY HandleTableEntry,
225 HANDLE Handle,
226 PVOID Context
227 );
228
229 typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK)(
230 PHANDLE_TABLE HandleTable,
231 PHANDLE_TABLE_ENTRY HandleTableEntry,
232 PVOID Context
233 );
234
235 typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK)(
236 PHANDLE_TABLE HandleTable,
237 PHANDLE_TABLE_ENTRY HandleTableEntry,
238 PVOID Context
239 );
240
241 VOID
242 ExpInitializeHandleTables(VOID);
243
244 PHANDLE_TABLE
245 ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL);
246
247 VOID
248 ExDestroyHandleTable(
249 IN PHANDLE_TABLE HandleTable
250 );
251
252 VOID
253 ExSweepHandleTable(
254 IN PHANDLE_TABLE HandleTable,
255 IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL,
256 IN PVOID Context OPTIONAL
257 );
258
259 PHANDLE_TABLE
260 ExDupHandleTable(
261 IN PEPROCESS QuotaProcess OPTIONAL,
262 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL,
263 IN PVOID Context OPTIONAL,
264 IN PHANDLE_TABLE SourceHandleTable
265 );
266
267 BOOLEAN
268 ExLockHandleTableEntry(
269 IN PHANDLE_TABLE HandleTable,
270 IN PHANDLE_TABLE_ENTRY Entry
271 );
272
273 VOID
274 ExUnlockHandleTableEntry(
275 IN PHANDLE_TABLE HandleTable,
276 IN PHANDLE_TABLE_ENTRY Entry
277 );
278
279 HANDLE
280 ExCreateHandle(
281 IN PHANDLE_TABLE HandleTable,
282 IN PHANDLE_TABLE_ENTRY Entry
283 );
284
285 BOOLEAN
286 ExDestroyHandle(
287 IN PHANDLE_TABLE HandleTable,
288 IN HANDLE Handle
289 );
290
291 VOID
292 ExDestroyHandleByEntry(
293 IN PHANDLE_TABLE HandleTable,
294 IN PHANDLE_TABLE_ENTRY Entry,
295 IN HANDLE Handle
296 );
297
298 PHANDLE_TABLE_ENTRY
299 ExMapHandleToPointer(
300 IN PHANDLE_TABLE HandleTable,
301 IN HANDLE Handle
302 );
303
304 BOOLEAN
305 ExChangeHandle(
306 IN PHANDLE_TABLE HandleTable,
307 IN HANDLE Handle,
308 IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
309 IN PVOID Context
310 );
311
312 /* PSEH EXCEPTION HANDLING **************************************************/
313
314 LONG
315 NTAPI
316 ExSystemExceptionFilter(VOID);
317
318 static __inline _SEH_FILTER(_SEH_ExSystemExceptionFilter)
319 {
320 return ExSystemExceptionFilter();
321 }
322
323 /* RUNDOWN *******************************************************************/
324
325 #ifdef _WIN64
326 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
327 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
328 #else
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)
332 #endif
333
334 /*++
335 * @name ExfAcquireRundownProtection
336 * INTERNAL MACRO
337 *
338 * The ExfAcquireRundownProtection routine acquires rundown protection for
339 * the specified descriptor.
340 *
341 * @param RunRef
342 * Pointer to a rundown reference descriptor.
343 *
344 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
345 *
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
348 * function.
349 *
350 *--*/
351 BOOLEAN
352 FORCEINLINE
353 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
354 {
355 ULONG_PTR Value, NewValue, OldValue;
356
357 /* Get the current value and mask the active bit */
358 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
359
360 /* Add a reference */
361 NewValue = Value + EX_RUNDOWN_COUNT_INC;
362
363 /* Change the value */
364 OldValue = ExpChangeRundown(RunRef, NewValue, Value);
365 if (OldValue != Value)
366 {
367 /* Rundown was active, use long path */
368 return ExfAcquireRundownProtection(RunRef);
369 }
370
371 /* Success */
372 return TRUE;
373 }
374
375 /*++
376 * @name ExReleaseRundownProtection
377 * INTERNAL MACRO
378 *
379 * The ExReleaseRundownProtection routine releases rundown protection for
380 * the specified descriptor.
381 *
382 * @param RunRef
383 * Pointer to a rundown reference descriptor.
384 *
385 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
386 *
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
389 * function.
390 *
391 *--*/
392 VOID
393 FORCEINLINE
394 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
395 {
396 ULONG_PTR Value, NewValue, OldValue;
397
398 /* Get the current value and mask the active bit */
399 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
400
401 /* Remove a reference */
402 NewValue = Value - EX_RUNDOWN_COUNT_INC;
403
404 /* Change the value */
405 OldValue = ExpChangeRundown(RunRef, NewValue, Value);
406
407 /* Check if the rundown was active */
408 if (OldValue != Value)
409 {
410 /* Rundown was active, use long path */
411 ExfReleaseRundownProtection(RunRef);
412 }
413 else
414 {
415 /* Sanity check */
416 ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
417 }
418 }
419
420 /*++
421 * @name ExInitializeRundownProtection
422 * INTERNAL MACRO
423 *
424 * The ExInitializeRundownProtection routine initializes a rundown
425 * protection descriptor.
426 *
427 * @param RunRef
428 * Pointer to a rundown reference descriptor.
429 *
430 * @return None.
431 *
432 * @remarks This is the internal macro for system use only.
433 *
434 *--*/
435 VOID
436 FORCEINLINE
437 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
438 {
439 /* Set the count to zero */
440 RunRef->Count = 0;
441 }
442
443 /*++
444 * @name ExWaitForRundownProtectionRelease
445 * INTERNAL MACRO
446 *
447 * The ExWaitForRundownProtectionRelease routine waits until the specified
448 * rundown descriptor has been released.
449 *
450 * @param RunRef
451 * Pointer to a rundown reference descriptor.
452 *
453 * @return None.
454 *
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.
457 *
458 *--*/
459 VOID
460 FORCEINLINE
461 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
462 {
463 ULONG_PTR Value;
464
465 /* Set the active bit */
466 Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
467 if ((Value) || (Value != EX_RUNDOWN_ACTIVE))
468 {
469 /* If the the rundown wasn't already active, then take the long path */
470 ExfWaitForRundownProtectionRelease(RunRef);
471 }
472 }
473
474 /*++
475 * @name ExRundownCompleted
476 * INTERNAL MACRO
477 *
478 * The ExRundownCompleted routine completes the rundown of the specified
479 * descriptor by setting the active bit.
480 *
481 * @param RunRef
482 * Pointer to a rundown reference descriptor.
483 *
484 * @return None.
485 *
486 * @remarks This is the internal macro for system use only.
487 *
488 *--*/
489 VOID
490 FORCEINLINE
491 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
492 {
493 /* Sanity check */
494 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
495
496 /* Mark the counter as active */
497 ExpSetRundown(&RunRef->Count, EX_RUNDOWN_ACTIVE);
498 }
499
500 /* PUSHLOCKS *****************************************************************/
501
502 /*++
503 * @name ExInitializePushLock
504 * INTERNAL MACRO
505 *
506 * The ExInitializePushLock macro initializes a PushLock.
507 *
508 * @params PushLock
509 * Pointer to the pushlock which is to be initialized.
510 *
511 * @return None.
512 *
513 * @remarks None.
514 *
515 *--*/
516 VOID
517 FORCEINLINE
518 ExInitializePushLock(IN PEX_PUSH_LOCK PushLock)
519 {
520 /* Set the value to 0 */
521 PushLock->Value = 0;
522 }
523
524 /*++
525 * @name ExAcquirePushLockExclusive
526 * INTERNAL MACRO
527 *
528 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
529 *
530 * @params PushLock
531 * Pointer to the pushlock which is to be acquired.
532 *
533 * @return None.
534 *
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.
538 *
539 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
540 * This macro should usually be paired up with KeAcquireCriticalRegion.
541 *
542 *--*/
543 VOID
544 FORCEINLINE
545 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
546 {
547 /* Try acquiring the lock */
548 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
549 {
550 /* Someone changed it, use the slow path */
551 DbgPrint("%s - Contention!\n", __FUNCTION__);
552 ExfAcquirePushLockExclusive(PushLock);
553 }
554
555 /* Sanity check */
556 ASSERT(PushLock->Locked);
557 }
558
559 /*++
560 * @name ExAcquirePushLockShared
561 * INTERNAL MACRO
562 *
563 * The ExAcquirePushLockShared macro acquires a shared PushLock.
564 *
565 * @params PushLock
566 * Pointer to the pushlock which is to be acquired.
567 *
568 * @return None.
569 *
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.
573 *
574 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
575 * This macro should usually be paired up with KeAcquireCriticalRegion.
576 *
577 *--*/
578 VOID
579 FORCEINLINE
580 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
581 {
582 EX_PUSH_LOCK NewValue;
583
584 /* Try acquiring the lock */
585 NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
586 if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
587 {
588 /* Someone changed it, use the slow path */
589 DbgPrint("%s - Contention!\n", __FUNCTION__);
590 ExfAcquirePushLockShared(PushLock);
591 }
592
593 /* Sanity checks */
594 ASSERT(PushLock->Locked);
595 ASSERT(PushLock->Waiting || PushLock->Shared > 0);
596 }
597
598 /*++
599 * @name ExConvertPushLockSharedToExclusive
600 * INTERNAL MACRO
601 *
602 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
603 * pushlock to a shared pushlock.
604 *
605 * @params PushLock
606 * Pointer to the pushlock which is to be converted.
607 *
608 * @return FALSE if conversion failed, TRUE otherwise.
609 *
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.
612 *
613 *--*/
614 BOOLEAN
615 FORCEINLINE
616 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
617 {
618 EX_PUSH_LOCK OldValue;
619
620 /* Set the expected old value */
621 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
622
623 /* Try converting the lock */
624 if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) !=
625 OldValue.Ptr)
626 {
627 /* Conversion failed */
628 return FALSE;
629 }
630
631 /* Sanity check */
632 ASSERT(PushLock->Locked);
633 return TRUE;
634 }
635
636 /*++
637 * @name ExWaitOnPushLock
638 * INTERNAL MACRO
639 *
640 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
641 *
642 * @params PushLock
643 * Pointer to a pushlock.
644 *
645 * @return None.
646 *
647 * @remarks The function attempts to get any exclusive waiters out of their slow
648 * path by forcing an instant acquire/release operation.
649 *
650 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
651 *
652 *--*/
653 VOID
654 FORCEINLINE
655 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
656 {
657 /* Acquire the lock */
658 ExfAcquirePushLockExclusive(PushLock);
659 ASSERT(PushLock->Locked);
660
661 /* Release it */
662 ExfReleasePushLockExclusive(PushLock);
663 }
664
665 /*++
666 * @name ExReleasePushLockShared
667 * INTERNAL MACRO
668 *
669 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
670 *
671 * @params PushLock
672 * Pointer to a previously acquired pushlock.
673 *
674 * @return None.
675 *
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.
679 *
680 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
681 * This macro should usually be paired up with KeLeaveCriticalRegion.
682 *
683 *--*/
684 VOID
685 FORCEINLINE
686 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
687 {
688 EX_PUSH_LOCK OldValue;
689
690 /* Sanity checks */
691 ASSERT(PushLock->Locked);
692 ASSERT(PushLock->Waiting || PushLock->Shared > 0);
693
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)
697 {
698 /* There are still other people waiting on it */
699 DbgPrint("%s - Contention!\n", __FUNCTION__);
700 ExfReleasePushLockShared(PushLock);
701 }
702 }
703
704 /*++
705 * @name ExReleasePushLockExclusive
706 * INTERNAL MACRO
707 *
708 * The ExReleasePushLockExclusive macro releases a previously
709 * exclusively acquired PushLock.
710 *
711 * @params PushLock
712 * Pointer to a previously acquired pushlock.
713 *
714 * @return None.
715 *
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.
720 *
721 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
722 * This macro should usually be paired up with KeLeaveCriticalRegion.
723 *
724 *--*/
725 VOID
726 FORCEINLINE
727 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
728 {
729 EX_PUSH_LOCK OldValue;
730
731 /* Sanity checks */
732 ASSERT(PushLock->Locked);
733 ASSERT(PushLock->Waiting || PushLock->Shared == 0);
734
735 /* Unlock the pushlock */
736 OldValue.Value = InterlockedExchangeAddSizeT((PLONG)PushLock, -1);
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 */