Silence compiler warnings (2/11).
[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 extern LIST_ENTRY ExpSystemResourcesList;
21 ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
22 ULONG ExpUnicodeCaseTableDataOffset;
23 PVOID ExpNlsSectionPointer;
24 extern CHAR NtBuildLab[];
25 extern ULONG CmNtCSDVersion;
26 extern ULONG NtGlobalFlag;
27 extern ULONG ExpInitializationPhase;
28 extern ULONG ExpAltTimeZoneBias;
29 extern LIST_ENTRY ExSystemLookasideListHead;
30
31 typedef struct _EXHANDLE
32 {
33 union
34 {
35 struct
36 {
37 ULONG TagBits:2;
38 ULONG Index:30;
39 };
40 HANDLE GenericHandleOverlay;
41 ULONG_PTR Value;
42 };
43 } EXHANDLE, *PEXHANDLE;
44
45 typedef struct _ETIMER
46 {
47 KTIMER KeTimer;
48 KAPC TimerApc;
49 KDPC TimerDpc;
50 LIST_ENTRY ActiveTimerListEntry;
51 KSPIN_LOCK Lock;
52 LONG Period;
53 BOOLEAN ApcAssociated;
54 BOOLEAN WakeTimer;
55 LIST_ENTRY WakeTimerListEntry;
56 } ETIMER, *PETIMER;
57
58 typedef struct
59 {
60 PCALLBACK_OBJECT *CallbackObject;
61 PWSTR Name;
62 } SYSTEM_CALLBACKS;
63
64 #define MAX_FAST_REFS 7
65
66 #define ExAcquireRundownProtection _ExAcquireRundownProtection
67 #define ExReleaseRundownProtection _ExReleaseRundownProtection
68 #define ExInitializeRundownProtection _ExInitializeRundownProtection
69 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
70 #define ExRundownCompleted _ExRundownCompleted
71 #define ExGetPreviousMode KeGetPreviousMode
72
73
74 //
75 // Various bits tagged on the handle or handle table
76 //
77 #define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1
78 #define FREE_HANDLE_MASK -1
79
80 //
81 // Number of entries in each table level
82 //
83 #define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
84 #define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
85 #define HIGH_LEVEL_ENTRIES (16777216 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
86
87 //
88 // Maximum index in each table level before we need another table
89 //
90 #define MAX_LOW_INDEX LOW_LEVEL_ENTRIES
91 #define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
92 #define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
93
94 //
95 // Detect old GCC
96 //
97 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40300)
98
99 #define DEFINE_WAIT_BLOCK(x) \
100 struct _AlignHack \
101 { \
102 UCHAR Hack[15]; \
103 EX_PUSH_LOCK_WAIT_BLOCK UnalignedBlock; \
104 } WaitBlockBuffer; \
105 PEX_PUSH_LOCK_WAIT_BLOCK x = (PEX_PUSH_LOCK_WAIT_BLOCK) \
106 ((ULONG_PTR)&WaitBlockBuffer.UnalignedBlock &~ 0xF);
107
108 #else
109
110 //
111 // This is only for compatibility; the compiler will optimize the extra
112 // local variable (the actual pointer) away, so we don't take any perf hit
113 // by doing this.
114 //
115 #define DEFINE_WAIT_BLOCK(x) \
116 EX_PUSH_LOCK_WAIT_BLOCK WaitBlockBuffer; \
117 PEX_PUSH_LOCK_WAIT_BLOCK x = &WaitBlockBuffer;
118
119 #endif
120
121 /* INITIALIZATION FUNCTIONS *************************************************/
122
123 VOID
124 NTAPI
125 ExpWin32kInit(VOID);
126
127 VOID
128 NTAPI
129 ExInit2(VOID);
130
131 VOID
132 NTAPI
133 Phase1Initialization(
134 IN PVOID Context
135 );
136
137 VOID
138 NTAPI
139 ExpInitializePushLocks(VOID);
140
141 BOOLEAN
142 NTAPI
143 ExRefreshTimeZoneInformation(
144 IN PLARGE_INTEGER SystemBootTime
145 );
146
147 VOID
148 NTAPI
149 ExpInitializeWorkerThreads(VOID);
150
151 VOID
152 NTAPI
153 ExpInitLookasideLists(VOID);
154
155 VOID
156 NTAPI
157 ExInitializeSystemLookasideList(
158 IN PGENERAL_LOOKASIDE List,
159 IN POOL_TYPE Type,
160 IN ULONG Size,
161 IN ULONG Tag,
162 IN USHORT MaximumDepth,
163 IN PLIST_ENTRY ListHead
164 );
165
166 BOOLEAN
167 NTAPI
168 ExpInitializeCallbacks(VOID);
169
170 VOID
171 NTAPI
172 ExpInitUuids(VOID);
173
174 VOID
175 NTAPI
176 ExpInitializeExecutive(
177 IN ULONG Cpu,
178 IN PLOADER_PARAMETER_BLOCK LoaderBlock
179 );
180
181 VOID
182 NTAPI
183 ExpInitializeEventImplementation(VOID);
184
185 VOID
186 NTAPI
187 ExpInitializeEventImplementation(VOID);
188
189 VOID
190 NTAPI
191 ExpInitializeEventPairImplementation(VOID);
192
193 VOID
194 NTAPI
195 ExpInitializeSemaphoreImplementation(VOID);
196
197 VOID
198 NTAPI
199 ExpInitializeMutantImplementation(VOID);
200
201 VOID
202 NTAPI
203 ExpInitializeTimerImplementation(VOID);
204
205 VOID
206 NTAPI
207 ExpInitializeProfileImplementation(VOID);
208
209 VOID
210 NTAPI
211 ExpResourceInitialization(VOID);
212
213 VOID
214 NTAPI
215 ExInitPoolLookasidePointers(VOID);
216
217 /* Callback Functions ********************************************************/
218
219 VOID
220 NTAPI
221 ExInitializeCallBack(
222 IN OUT PEX_CALLBACK Callback
223 );
224
225 PEX_CALLBACK_ROUTINE_BLOCK
226 NTAPI
227 ExAllocateCallBack(
228 IN PEX_CALLBACK_FUNCTION Function,
229 IN PVOID Context
230 );
231
232 VOID
233 NTAPI
234 ExFreeCallBack(
235 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
236 );
237
238 BOOLEAN
239 NTAPI
240 ExCompareExchangeCallBack (
241 IN OUT PEX_CALLBACK CallBack,
242 IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
243 IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
244 );
245
246 PEX_CALLBACK_ROUTINE_BLOCK
247 NTAPI
248 ExReferenceCallBackBlock(
249 IN OUT PEX_CALLBACK CallBack
250 );
251
252 VOID
253 NTAPI
254 ExDereferenceCallBackBlock(
255 IN OUT PEX_CALLBACK CallBack,
256 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
257 );
258
259 PEX_CALLBACK_FUNCTION
260 NTAPI
261 ExGetCallBackBlockRoutine(
262 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
263 );
264
265 PVOID
266 NTAPI
267 ExGetCallBackBlockContext(
268 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
269 );
270
271 VOID
272 NTAPI
273 ExWaitForCallBacks(
274 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
275 );
276
277 /* Rundown Functions ********************************************************/
278
279 VOID
280 FASTCALL
281 ExfInitializeRundownProtection(
282 OUT PEX_RUNDOWN_REF RunRef
283 );
284
285 VOID
286 FASTCALL
287 ExfReInitializeRundownProtection(
288 OUT PEX_RUNDOWN_REF RunRef
289 );
290
291 BOOLEAN
292 FASTCALL
293 ExfAcquireRundownProtection(
294 IN OUT PEX_RUNDOWN_REF RunRef
295 );
296
297 BOOLEAN
298 FASTCALL
299 ExfAcquireRundownProtectionEx(
300 IN OUT PEX_RUNDOWN_REF RunRef,
301 IN ULONG Count
302 );
303
304 VOID
305 FASTCALL
306 ExfReleaseRundownProtection(
307 IN OUT PEX_RUNDOWN_REF RunRef
308 );
309
310 VOID
311 FASTCALL
312 ExfReleaseRundownProtectionEx(
313 IN OUT PEX_RUNDOWN_REF RunRef,
314 IN ULONG Count
315 );
316
317 VOID
318 FASTCALL
319 ExfRundownCompleted(
320 OUT PEX_RUNDOWN_REF RunRef
321 );
322
323 VOID
324 FASTCALL
325 ExfWaitForRundownProtectionRelease(
326 IN OUT PEX_RUNDOWN_REF RunRef
327 );
328
329 /* HANDLE TABLE FUNCTIONS ***************************************************/
330
331 typedef BOOLEAN
332 (NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
333 PHANDLE_TABLE_ENTRY HandleTableEntry,
334 HANDLE Handle,
335 PVOID Context
336 );
337
338 typedef BOOLEAN
339 (NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
340 IN PEPROCESS Process,
341 IN PHANDLE_TABLE HandleTable,
342 IN PHANDLE_TABLE_ENTRY HandleTableEntry,
343 IN PHANDLE_TABLE_ENTRY NewEntry
344 );
345
346 typedef BOOLEAN
347 (NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
348 PHANDLE_TABLE_ENTRY HandleTableEntry,
349 ULONG_PTR Context
350 );
351
352 VOID
353 NTAPI
354 ExpInitializeHandleTables(
355 VOID
356 );
357
358 PHANDLE_TABLE
359 NTAPI
360 ExCreateHandleTable(
361 IN PEPROCESS Process OPTIONAL
362 );
363
364 VOID
365 NTAPI
366 ExUnlockHandleTableEntry(
367 IN PHANDLE_TABLE HandleTable,
368 IN PHANDLE_TABLE_ENTRY HandleTableEntry
369 );
370
371 HANDLE
372 NTAPI
373 ExCreateHandle(
374 IN PHANDLE_TABLE HandleTable,
375 IN PHANDLE_TABLE_ENTRY HandleTableEntry
376 );
377
378 VOID
379 NTAPI
380 ExDestroyHandleTable(
381 IN PHANDLE_TABLE HandleTable,
382 IN PVOID DestroyHandleProcedure OPTIONAL
383 );
384
385 BOOLEAN
386 NTAPI
387 ExDestroyHandle(
388 IN PHANDLE_TABLE HandleTable,
389 IN HANDLE Handle,
390 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
391 );
392
393 PHANDLE_TABLE_ENTRY
394 NTAPI
395 ExMapHandleToPointer(
396 IN PHANDLE_TABLE HandleTable,
397 IN HANDLE Handle
398 );
399
400 PHANDLE_TABLE
401 NTAPI
402 ExDupHandleTable(
403 IN PEPROCESS Process,
404 IN PHANDLE_TABLE HandleTable,
405 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
406 IN ULONG_PTR Mask
407 );
408
409 BOOLEAN
410 NTAPI
411 ExChangeHandle(
412 IN PHANDLE_TABLE HandleTable,
413 IN HANDLE Handle,
414 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
415 IN ULONG_PTR Context
416 );
417
418 VOID
419 NTAPI
420 ExSweepHandleTable(
421 IN PHANDLE_TABLE HandleTable,
422 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
423 IN PVOID Context
424 );
425
426 /* PSEH EXCEPTION HANDLING **************************************************/
427
428 LONG
429 NTAPI
430 ExSystemExceptionFilter(VOID);
431
432 /* CALLBACKS *****************************************************************/
433
434 FORCEINLINE
435 VOID
436 ExDoCallBack(IN OUT PEX_CALLBACK Callback,
437 IN PVOID Context,
438 IN PVOID Argument1,
439 IN PVOID Argument2)
440 {
441 PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock;
442 PEX_CALLBACK_FUNCTION Function;
443
444 /* Reference the block */
445 CallbackRoutineBlock = ExReferenceCallBackBlock(Callback);
446 if (CallbackRoutineBlock)
447 {
448 /* Get the function */
449 Function = ExGetCallBackBlockRoutine(CallbackRoutineBlock);
450
451 /* Do the callback */
452 Function(Context, Argument1, Argument2);
453
454 /* Now dereference it */
455 ExDereferenceCallBackBlock(Callback, CallbackRoutineBlock);
456 }
457 }
458
459 /* RUNDOWN *******************************************************************/
460
461 #ifdef _WIN64
462 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
463 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
464 #else
465 #define ExpChangeRundown(x, y, z) PtrToUlong(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
466 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
467 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
468 #endif
469
470 /*++
471 * @name ExfAcquireRundownProtection
472 * INTERNAL MACRO
473 *
474 * The ExfAcquireRundownProtection routine acquires rundown protection for
475 * the specified descriptor.
476 *
477 * @param RunRef
478 * Pointer to a rundown reference descriptor.
479 *
480 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
481 *
482 * @remarks This is the internal macro for system use only.In case the rundown
483 * was active, then the slow-path will be called through the exported
484 * function.
485 *
486 *--*/
487 FORCEINLINE
488 BOOLEAN
489 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
490 {
491 ULONG_PTR Value, NewValue;
492
493 /* Get the current value and mask the active bit */
494 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
495
496 /* Add a reference */
497 NewValue = Value + EX_RUNDOWN_COUNT_INC;
498
499 /* Change the value */
500 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
501 if (NewValue != Value)
502 {
503 /* Rundown was active, use long path */
504 return ExfAcquireRundownProtection(RunRef);
505 }
506
507 /* Success */
508 return TRUE;
509 }
510
511 /*++
512 * @name ExReleaseRundownProtection
513 * INTERNAL MACRO
514 *
515 * The ExReleaseRundownProtection routine releases rundown protection for
516 * the specified descriptor.
517 *
518 * @param RunRef
519 * Pointer to a rundown reference descriptor.
520 *
521 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
522 *
523 * @remarks This is the internal macro for system use only.In case the rundown
524 * was active, then the slow-path will be called through the exported
525 * function.
526 *
527 *--*/
528 FORCEINLINE
529 VOID
530 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
531 {
532 ULONG_PTR Value, NewValue;
533
534 /* Get the current value and mask the active bit */
535 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
536
537 /* Remove a reference */
538 NewValue = Value - EX_RUNDOWN_COUNT_INC;
539
540 /* Change the value */
541 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
542
543 /* Check if the rundown was active */
544 if (NewValue != Value)
545 {
546 /* Rundown was active, use long path */
547 ExfReleaseRundownProtection(RunRef);
548 }
549 else
550 {
551 /* Sanity check */
552 ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
553 }
554 }
555
556 /*++
557 * @name ExInitializeRundownProtection
558 * INTERNAL MACRO
559 *
560 * The ExInitializeRundownProtection routine initializes a rundown
561 * protection descriptor.
562 *
563 * @param RunRef
564 * Pointer to a rundown reference descriptor.
565 *
566 * @return None.
567 *
568 * @remarks This is the internal macro for system use only.
569 *
570 *--*/
571 FORCEINLINE
572 VOID
573 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
574 {
575 /* Set the count to zero */
576 RunRef->Count = 0;
577 }
578
579 /*++
580 * @name ExWaitForRundownProtectionRelease
581 * INTERNAL MACRO
582 *
583 * The ExWaitForRundownProtectionRelease routine waits until the specified
584 * rundown descriptor has been released.
585 *
586 * @param RunRef
587 * Pointer to a rundown reference descriptor.
588 *
589 * @return None.
590 *
591 * @remarks This is the internal macro for system use only. If a wait is actually
592 * necessary, then the slow path is taken through the exported function.
593 *
594 *--*/
595 FORCEINLINE
596 VOID
597 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
598 {
599 ULONG_PTR Value;
600
601 /* Set the active bit */
602 Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
603 if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
604 {
605 /* If the the rundown wasn't already active, then take the long path */
606 ExfWaitForRundownProtectionRelease(RunRef);
607 }
608 }
609
610 /*++
611 * @name ExRundownCompleted
612 * INTERNAL MACRO
613 *
614 * The ExRundownCompleted routine completes the rundown of the specified
615 * descriptor by setting the active bit.
616 *
617 * @param RunRef
618 * Pointer to a rundown reference descriptor.
619 *
620 * @return None.
621 *
622 * @remarks This is the internal macro for system use only.
623 *
624 *--*/
625 FORCEINLINE
626 VOID
627 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
628 {
629 /* Sanity check */
630 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
631
632 /* Mark the counter as active */
633 ExpSetRundown(&RunRef->Count, EX_RUNDOWN_ACTIVE);
634 }
635
636 /* PUSHLOCKS *****************************************************************/
637
638 /* FIXME: VERIFY THESE! */
639
640 VOID
641 FASTCALL
642 ExBlockPushLock(
643 IN PEX_PUSH_LOCK PushLock,
644 IN PVOID WaitBlock
645 );
646
647 VOID
648 FASTCALL
649 ExfUnblockPushLock(
650 IN PEX_PUSH_LOCK PushLock,
651 IN PVOID CurrentWaitBlock
652 );
653
654 VOID
655 FASTCALL
656 ExWaitForUnblockPushLock(
657 IN PEX_PUSH_LOCK PushLock,
658 IN PVOID WaitBlock
659 );
660
661 /*++
662 * @name ExInitializePushLock
663 * INTERNAL MACRO
664 *
665 * The ExInitializePushLock macro initializes a PushLock.
666 *
667 * @params PushLock
668 * Pointer to the pushlock which is to be initialized.
669 *
670 * @return None.
671 *
672 * @remarks None.
673 *
674 *--*/
675 FORCEINLINE
676 VOID
677 ExInitializePushLock(IN PULONG_PTR PushLock)
678 {
679 /* Set the value to 0 */
680 *PushLock = 0;
681 }
682
683 /*++
684 * @name ExAcquirePushLockExclusive
685 * INTERNAL MACRO
686 *
687 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
688 *
689 * @params PushLock
690 * Pointer to the pushlock which is to be acquired.
691 *
692 * @return None.
693 *
694 * @remarks The function attempts the quickest route to acquire the lock, which is
695 * to simply set the lock bit.
696 * However, if the pushlock is already shared, the slower path is taken.
697 *
698 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
699 * This macro should usually be paired up with KeAcquireCriticalRegion.
700 *
701 *--*/
702 FORCEINLINE
703 VOID
704 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
705 {
706 /* Try acquiring the lock */
707 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
708 {
709 /* Someone changed it, use the slow path */
710 ExfAcquirePushLockExclusive(PushLock);
711 }
712
713 /* Sanity check */
714 ASSERT(PushLock->Locked);
715 }
716
717 /*++
718 * @name ExTryToAcquirePushLockExclusive
719 * INTERNAL MACRO
720 *
721 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
722 *
723 * @params PushLock
724 * Pointer to the pushlock which is to be acquired.
725 *
726 * @return None.
727 *
728 * @remarks The function attempts the quickest route to acquire the lock, which is
729 * to simply set the lock bit.
730 * However, if the pushlock is already shared, the slower path is taken.
731 *
732 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
733 * This macro should usually be paired up with KeAcquireCriticalRegion.
734 *
735 *--*/
736 FORCEINLINE
737 BOOLEAN
738 ExTryToAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
739 {
740 /* Try acquiring the lock */
741 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
742 {
743 /* Can't acquire */
744 return FALSE;
745 }
746
747 /* Got acquired */
748 ASSERT (PushLock->Locked);
749 return TRUE;
750 }
751
752 /*++
753 * @name ExAcquirePushLockShared
754 * INTERNAL MACRO
755 *
756 * The ExAcquirePushLockShared macro acquires a shared PushLock.
757 *
758 * @params PushLock
759 * Pointer to the pushlock which is to be acquired.
760 *
761 * @return None.
762 *
763 * @remarks The function attempts the quickest route to acquire the lock, which is
764 * to simply set the lock bit and set the share count to one.
765 * However, if the pushlock is already shared, the slower path is taken.
766 *
767 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
768 * This macro should usually be paired up with KeAcquireCriticalRegion.
769 *
770 *--*/
771 FORCEINLINE
772 VOID
773 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
774 {
775 EX_PUSH_LOCK NewValue;
776
777 /* Try acquiring the lock */
778 NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
779 if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
780 {
781 /* Someone changed it, use the slow path */
782 ExfAcquirePushLockShared(PushLock);
783 }
784
785 /* Sanity checks */
786 ASSERT(PushLock->Locked);
787 ASSERT(PushLock->Waiting || PushLock->Shared > 0);
788 }
789
790 /*++
791 * @name ExConvertPushLockSharedToExclusive
792 * INTERNAL MACRO
793 *
794 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
795 * pushlock to a shared pushlock.
796 *
797 * @params PushLock
798 * Pointer to the pushlock which is to be converted.
799 *
800 * @return FALSE if conversion failed, TRUE otherwise.
801 *
802 * @remarks The function attempts the quickest route to convert the lock, which is
803 * to simply set the lock bit and remove any other bits.
804 *
805 *--*/
806 FORCEINLINE
807 BOOLEAN
808 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
809 {
810 EX_PUSH_LOCK OldValue;
811
812 /* Set the expected old value */
813 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
814
815 /* Try converting the lock */
816 if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) !=
817 OldValue.Ptr)
818 {
819 /* Conversion failed */
820 return FALSE;
821 }
822
823 /* Sanity check */
824 ASSERT(PushLock->Locked);
825 return TRUE;
826 }
827
828 /*++
829 * @name ExWaitOnPushLock
830 * INTERNAL MACRO
831 *
832 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
833 *
834 * @params PushLock
835 * Pointer to a pushlock.
836 *
837 * @return None.
838 *
839 * @remarks The function attempts to get any exclusive waiters out of their slow
840 * path by forcing an instant acquire/release operation.
841 *
842 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
843 *
844 *--*/
845 FORCEINLINE
846 VOID
847 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
848 {
849 /* Check if we're locked */
850 if (PushLock->Locked)
851 {
852 /* Acquire the lock */
853 ExfAcquirePushLockExclusive(PushLock);
854 ASSERT(PushLock->Locked);
855
856 /* Release it */
857 ExfReleasePushLockExclusive(PushLock);
858 }
859 }
860
861 /*++
862 * @name ExReleasePushLockShared
863 * INTERNAL MACRO
864 *
865 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
866 *
867 * @params PushLock
868 * Pointer to a previously acquired pushlock.
869 *
870 * @return None.
871 *
872 * @remarks The function attempts the quickest route to release the lock, which is
873 * to simply decrease the share count and remove the lock bit.
874 * However, if the pushlock is being waited on then the long path is taken.
875 *
876 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
877 * This macro should usually be paired up with KeLeaveCriticalRegion.
878 *
879 *--*/
880 FORCEINLINE
881 VOID
882 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
883 {
884 EX_PUSH_LOCK OldValue;
885
886 /* Sanity checks */
887 ASSERT(PushLock->Locked);
888 ASSERT(PushLock->Waiting || PushLock->Shared > 0);
889
890 /* Try to clear the pushlock */
891 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
892 if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr)
893 {
894 /* There are still other people waiting on it */
895 ExfReleasePushLockShared(PushLock);
896 }
897 }
898
899 /*++
900 * @name ExReleasePushLockExclusive
901 * INTERNAL MACRO
902 *
903 * The ExReleasePushLockExclusive macro releases a previously
904 * exclusively acquired PushLock.
905 *
906 * @params PushLock
907 * Pointer to a previously acquired pushlock.
908 *
909 * @return None.
910 *
911 * @remarks The function attempts the quickest route to release the lock, which is
912 * to simply clear the locked bit.
913 * However, if the pushlock is being waited on, the slow path is taken
914 * in an attempt to wake up the lock.
915 *
916 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
917 * This macro should usually be paired up with KeLeaveCriticalRegion.
918 *
919 *--*/
920 FORCEINLINE
921 VOID
922 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
923 {
924 EX_PUSH_LOCK OldValue;
925
926 /* Sanity checks */
927 ASSERT(PushLock->Locked);
928 ASSERT(PushLock->Waiting || PushLock->Shared == 0);
929
930 /* Unlock the pushlock */
931 OldValue.Value = InterlockedExchangeAddSizeT((PLONG)PushLock,
932 -(LONG)EX_PUSH_LOCK_LOCK);
933
934 /* Sanity checks */
935 ASSERT(OldValue.Locked);
936 ASSERT(OldValue.Waiting || OldValue.Shared == 0);
937
938 /* Check if anyone is waiting on it and it's not already waking*/
939 if ((OldValue.Waiting) && !(OldValue.Waking))
940 {
941 /* Wake it up */
942 ExfTryToWakePushLock(PushLock);
943 }
944 }
945
946 /*++
947 * @name ExReleasePushLock
948 * INTERNAL MACRO
949 *
950 * The ExReleasePushLock macro releases a previously acquired PushLock.
951 *
952 * @params PushLock
953 * Pointer to a previously acquired pushlock.
954 *
955 * @return None.
956 *
957 * @remarks The function attempts the quickest route to release the lock, which is
958 * to simply clear all the fields and decrease the share count if required.
959 * However, if the pushlock is being waited on then the long path is taken.
960 *
961 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
962 * This macro should usually be paired up with KeLeaveCriticalRegion.
963 *
964 *--*/
965 FORCEINLINE
966 VOID
967 ExReleasePushLock(PEX_PUSH_LOCK PushLock)
968 {
969 EX_PUSH_LOCK OldValue = *PushLock;
970 EX_PUSH_LOCK NewValue;
971
972 /* Sanity checks */
973 ASSERT(OldValue.Locked);
974
975 /* Check if the pushlock is shared */
976 if (OldValue.Shared > 1)
977 {
978 /* Decrease the share count */
979 NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC;
980 }
981 else
982 {
983 /* Clear the pushlock entirely */
984 NewValue.Value = 0;
985 }
986
987 /* Check if nobody is waiting on us and try clearing the lock here */
988 if ((OldValue.Waiting) ||
989 (ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) !=
990 OldValue.Ptr))
991 {
992 /* We have waiters, use the long path */
993 ExfReleasePushLock(PushLock);
994 }
995 }
996
997 /* OTHER FUNCTIONS **********************************************************/
998
999 BOOLEAN
1000 NTAPI
1001 ExTryToAcquireResourceExclusiveLite(
1002 IN PERESOURCE Resource
1003 );
1004
1005 NTSTATUS
1006 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation);
1007
1008 BOOLEAN
1009 NTAPI
1010 ExAcquireTimeRefreshLock(BOOLEAN Wait);
1011
1012 VOID
1013 NTAPI
1014 ExReleaseTimeRefreshLock(VOID);
1015
1016 VOID
1017 NTAPI
1018 ExUpdateSystemTimeFromCmos(IN BOOLEAN UpdateInterruptTime,
1019 IN ULONG MaxSepInSeconds);
1020
1021 NTSTATUS
1022 NTAPI
1023 ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId);
1024
1025 VOID
1026 NTAPI
1027 ExTimerRundown(VOID);
1028
1029 VOID
1030 NTAPI
1031 HeadlessInit(
1032 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1033 );
1034
1035 VOID
1036 NTAPI
1037 XIPInit(
1038 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1039 );
1040
1041 #define InterlockedDecrementUL(Addend) \
1042 (ULONG)InterlockedDecrement((PLONG)(Addend))
1043
1044 #define InterlockedIncrementUL(Addend) \
1045 (ULONG)InterlockedIncrement((PLONG)(Addend))
1046
1047 #define InterlockedExchangeUL(Target, Value) \
1048 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
1049
1050 #define InterlockedExchangeAddUL(Addend, Value) \
1051 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
1052
1053 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
1054 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
1055
1056 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
1057 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
1058
1059 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */