ReactOS 0.4.16-dev-340-g0540c21
rundown.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/rundown.c
5 * PURPOSE: Rundown and Cache-Aware Rundown Protection
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Thomas Weidenmueller
8 * Pierre Schweitzer
9 */
10
11/* INCLUDES *****************************************************************/
12
13#include <ntoskrnl.h>
14#define NDEBUG
15#include <debug.h>
16
17/* FUNCTIONS *****************************************************************/
18
19/*++
20 * @name ExfAcquireRundownProtection
21 * @implemented NT5.1
22 *
23 * The ExfAcquireRundownProtection routine acquires rundown protection for
24 * the specified descriptor.
25 *
26 * @param RunRef
27 * Pointer to a rundown reference descriptor.
28 *
29 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
30 *
31 * @remarks Callers of ExfAcquireRundownProtection can be running at any IRQL.
32 *
33 *--*/
37{
38 ULONG_PTR Value = RunRef->Count, NewValue;
39
40 /* Loop until successfully incremented the counter */
41 for (;;)
42 {
43 /* Make sure a rundown is not active */
44 if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
45
46 /* Add a reference */
47 NewValue = Value + EX_RUNDOWN_COUNT_INC;
48
49 /* Change the value */
50 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
51 if (NewValue == Value) return TRUE;
52
53 /* Update it */
54 Value = NewValue;
55 }
56}
57
58/*++
59 * @name ExfAcquireRundownProtectionEx
60 * @implemented NT5.2
61 *
62 * The ExfAcquireRundownProtectionEx routine acquires multiple rundown
63 * protection references for the specified descriptor.
64 *
65 * @param RunRef
66 * Pointer to a rundown reference descriptor.
67 *
68 * @param Count
69 * Number of times to reference the descriptor.
70 *
71 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
72 *
73 * @remarks Callers of ExfAcquireRundownProtectionEx can be running at any IRQL.
74 *
75 *--*/
80{
81 ULONG_PTR Value = RunRef->Count, NewValue;
82
83 /* Loop until successfully incremented the counter */
84 for (;;)
85 {
86 /* Make sure a rundown is not active */
87 if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
88
89 /* Add references */
90 NewValue = Value + EX_RUNDOWN_COUNT_INC * Count;
91
92 /* Change the value */
93 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
94 if (NewValue == Value) return TRUE;
95
96 /* Update the value */
97 Value = NewValue;
98 }
99}
100
101/*++
102 * @name ExfInitializeRundownProtection
103 * @implemented NT5.1
104 *
105 * The ExfInitializeRundownProtection routine initializes a rundown
106 * protection descriptor.
107 *
108 * @param RunRef
109 * Pointer to a rundown reference descriptor.
110 *
111 * @return None.
112 *
113 * @remarks Callers of ExfInitializeRundownProtection can be running at any IRQL.
114 *
115 *--*/
116VOID
119{
120 /* Set the count to zero */
121 RunRef->Count = 0;
122}
123
124/*++
125 * @name ExfReInitializeRundownProtection
126 * @implemented NT5.1
127 *
128 * The ExfReInitializeRundownProtection routine re-initializes a rundown
129 * protection descriptor.
130 *
131 * @param RunRef
132 * Pointer to a rundown reference descriptor.
133 *
134 * @return None.
135 *
136 * @remarks Callers of ExfReInitializeRundownProtection can be running at any IRQL.
137 *
138 *--*/
139VOID
142{
143 PAGED_CODE();
144
145 /* Sanity check */
146 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
147
148 /* Reset the count */
149 ExpSetRundown(RunRef, 0);
150}
151
152/*++
153 * @name ExfRundownCompleted
154 * @implemented NT5.1
155 *
156 * The ExfRundownCompleted routine completes the rundown of the specified
157 * descriptor by setting the active bit.
158 *
159 * @param RunRef
160 * Pointer to a rundown reference descriptor.
161 *
162 * @return None.
163 *
164 * @remarks Callers of ExfRundownCompleted must be running at IRQL <= APC_LEVEL.
165 *
166 *--*/
167VOID
170{
171 PAGED_CODE();
172
173 /* Sanity check */
174 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
175
176 /* Mark the counter as active */
178}
179
180/*++
181 * @name ExfReleaseRundownProtection
182 * @implemented NT5.1
183 *
184 * The ExfReleaseRundownProtection routine releases the rundown protection
185 * reference for the specified descriptor.
186 *
187 * @param RunRef
188 * Pointer to a rundown reference descriptor.
189 *
190 * @return None.
191 *
192 * @remarks Callers of ExfReleaseRundownProtection can be running at any IRQL.
193 *
194 *--*/
195VOID
198{
199 ULONG_PTR Value = RunRef->Count, NewValue;
200 PEX_RUNDOWN_WAIT_BLOCK WaitBlock;
201
202 /* Loop until successfully incremented the counter */
203 for (;;)
204 {
205 /* Check if rundown is not active */
206 if (!(Value & EX_RUNDOWN_ACTIVE))
207 {
208 /* Sanity check */
210
211 /* Get the new value */
212 NewValue = Value - EX_RUNDOWN_COUNT_INC;
213
214 /* Change the value */
215 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
216 if (NewValue == Value) break;
217
218 /* Update value */
219 Value = NewValue;
220 }
221 else
222 {
223 /* Get the wait block */
225 ASSERT((WaitBlock->Count > 0) || (KeNumberProcessors > 1));
226
227 /* Remove the one count */
228 if (!InterlockedDecrementSizeT(&WaitBlock->Count))
229 {
230 /* We're down to 0 now, so signal the event */
232 }
233
234 /* We're all done */
235 break;
236 }
237 }
238}
239
240/*++
241 * @name ExfReleaseRundownProtectionEx
242 * @implemented NT5.2
243 *
244 * The ExfReleaseRundownProtectionEx routine releases multiple rundown
245 * protection references for the specified descriptor.
246 *
247 * @param RunRef
248 * Pointer to a rundown reference descriptor.
249 *
250 * @param Count
251 * Number of times to dereference the descriptor.
252 *
253 * @return None.
254 *
255 * @remarks Callers of ExfAcquireRundownProtectionEx can be running at any IRQL.
256 *
257 *--*/
258VOID
261 IN ULONG Count)
262{
263 ULONG_PTR Value = RunRef->Count, NewValue;
264 PEX_RUNDOWN_WAIT_BLOCK WaitBlock;
265
266 /* Loop until successfully incremented the counter */
267 for (;;)
268 {
269 /* Check if rundown is not active */
270 if (!(Value & EX_RUNDOWN_ACTIVE))
271 {
272 /* Sanity check */
274 (KeNumberProcessors > 1));
275
276 /* Get the new value */
277 NewValue = Value - EX_RUNDOWN_COUNT_INC * Count;
278
279 /* Change the value */
280 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
281 if (NewValue == Value) break;
282
283 /* Update value */
284 Value = NewValue;
285 }
286 else
287 {
288 /* Get the wait block */
290 ASSERT((WaitBlock->Count >= Count) || (KeNumberProcessors > 1));
291
292 /* Remove the counts */
293 if (InterlockedExchangeAddSizeT(&WaitBlock->Count,
294 -(LONG)Count) == (LONG)Count)
295 {
296 /* We're down to 0 now, so signal the event */
298 }
299
300 /* We're all done */
301 break;
302 }
303 }
304}
305
306/*++
307 * @name ExfWaitForRundownProtectionRelease
308 * @implemented NT5.1
309 *
310 * The ExfWaitForRundownProtectionRelease routine waits until the specified
311 * rundown descriptor has been released.
312 *
313 * @param RunRef
314 * Pointer to a rundown reference descriptor.
315 *
316 * @return None.
317 *
318 * @remarks Callers of ExfWaitForRundownProtectionRelease must be running
319 * at IRQL <= APC_LEVEL.
320 *
321 *--*/
322VOID
325{
326 ULONG_PTR Value, Count, NewValue;
327 EX_RUNDOWN_WAIT_BLOCK WaitBlock;
328 PEX_RUNDOWN_WAIT_BLOCK WaitBlockPointer;
330 PAGED_CODE();
331
332 /* Set the active bit */
334 if ((Value == 0) || (Value == EX_RUNDOWN_ACTIVE)) return;
335
336 /* No event for now */
337 Event = NULL;
338 WaitBlockPointer = (PEX_RUNDOWN_WAIT_BLOCK)((ULONG_PTR)&WaitBlock |
340
341 /* Start waitblock set loop */
342 for (;;)
343 {
344 /* Save the count */
346
347 /* If the count is over one and we don't have en event yet, create it */
348 if ((Count) && !(Event))
349 {
350 /* Initialize the event */
351 KeInitializeEvent(&WaitBlock.WakeEvent,
353 FALSE);
354
355 /* Set the pointer */
356 Event = &WaitBlock.WakeEvent;
357 }
358
359 /* Set the count */
360 WaitBlock.Count = Count;
361
362 /* Now set the pointer */
363 NewValue = ExpChangeRundown(RunRef, (ULONG_PTR)WaitBlockPointer, Value);
364 if (NewValue == Value) break;
365
366 /* Loop again */
367 Value = NewValue;
369 }
370
371 /* If the count was 0, we're done */
372 if (!Count) return;
373
374 /* Wait for whoever needs to release to notify us */
376 ASSERT(WaitBlock.Count == 0);
377}
378
379/*
380 * @implemented NT5.2
381 */
385{
386 PEX_RUNDOWN_REF RunRef;
387
388 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
389 return _ExAcquireRundownProtection(RunRef);
390}
391
392/*
393 * @implemented NT5.2
394 */
398 IN ULONG Count)
399{
400 PEX_RUNDOWN_REF RunRef;
401
402 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
403 return ExfAcquireRundownProtectionEx(RunRef, Count);
404}
405
406/*
407 * @implemented NT5.2
408 */
409VOID
412{
413 PEX_RUNDOWN_REF RunRef;
414
415 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
417}
418
419/*
420 * @implemented NT5.2
421 */
422VOID
425 IN ULONG Count)
426{
427 PEX_RUNDOWN_REF RunRef;
428
429 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
431}
432
433/*
434 * @implemented NT5.2
435 */
436VOID
439{
440 PEX_RUNDOWN_REF RunRef;
441 EX_RUNDOWN_WAIT_BLOCK WaitBlock;
442 PEX_RUNDOWN_WAIT_BLOCK WaitBlockPointer;
443 ULONG_PTR ProcCount, Current, Value, OldValue, TotalCount;
444
445 ProcCount = RunRefCacheAware->Number;
446 /* No proc, nothing to do */
447 if (ProcCount == 0)
448 {
449 return;
450 }
451
452 TotalCount = 0;
453 WaitBlock.Count = 0;
454 WaitBlockPointer = (PEX_RUNDOWN_WAIT_BLOCK)((ULONG_PTR)&WaitBlock |
456 /* We will check all our runrefs */
457 for (Current = 0; Current < ProcCount; ++Current)
458 {
459 /* Get the runref for the proc */
460 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Current);
461 /* Loop for setting the wait block */
462 do
463 {
464 Value = RunRef->Count;
466
467 /* Remove old value and set our waitblock instead */
468 OldValue = ExpChangeRundown(RunRef, WaitBlockPointer, Value);
469 if (OldValue == Value)
470 {
471 break;
472 }
473
474 Value = OldValue;
475 }
476 while (TRUE);
477
478 /* Count the deleted values */
479 TotalCount += Value;
480 }
481
482 /* Sanity check: we didn't overflow */
483 ASSERT((LONG_PTR)TotalCount >= 0);
484 if (TotalCount != 0)
485 {
486 /* Init the waitblock event */
487 KeInitializeEvent(&WaitBlock.WakeEvent,
489 FALSE);
490
491 /* Do we have to wait? If so, go ahead! */
492 if (InterlockedExchangeAddSizeT(&WaitBlock.Count,
493 (LONG_PTR)TotalCount >> EX_RUNDOWN_COUNT_SHIFT) ==
494 -(LONG_PTR)(TotalCount >> EX_RUNDOWN_COUNT_SHIFT))
495 {
497 }
498 }
499}
500
501/*
502 * @implemented NT5.2
503 */
504VOID
507{
508 PEX_RUNDOWN_REF RunRef;
509 ULONG ProcCount, Current;
510
511 ProcCount = RunRefCacheAware->Number;
512 /* No proc, nothing to do */
513 if (ProcCount == 0)
514 {
515 return;
516 }
517
518 /* We will mark all our runrefs active */
519 for (Current = 0; Current < ProcCount; ++Current)
520 {
521 /* Get the runref for the proc */
522 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Current);
523 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
524
526 }
527}
528
529/*
530 * @implemented NT5.2
531 */
532VOID
535{
536 PEX_RUNDOWN_REF RunRef;
537 ULONG ProcCount, Current;
538
539 ProcCount = RunRefCacheAware->Number;
540 /* No proc, nothing to do */
541 if (ProcCount == 0)
542 {
543 return;
544 }
545
546 /* We will mark all our runrefs inactive */
547 for (Current = 0; Current < ProcCount; ++Current)
548 {
549 /* Get the runref for the proc */
550 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Current);
551 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
552
553 ExpSetRundown(RunRef, 0);
554 }
555}
556
557/*
558 * @implemented NT5.2
559 */
561NTAPI
563 IN ULONG Tag)
564{
565 PEX_RUNDOWN_REF RunRef;
566 PVOID PoolToFree, RunRefs;
568 PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware;
569
570 PAGED_CODE();
571
572 /* Allocate the master structure */
573 RunRefCacheAware = ExAllocatePoolWithTag(PoolType, sizeof(EX_RUNDOWN_REF_CACHE_AWARE), Tag);
574 if (RunRefCacheAware == NULL)
575 {
576 return NULL;
577 }
578
579 /* Compute the size of each runref */
580 RunRefCacheAware->Number = KeNumberProcessors;
581 if (KeNumberProcessors <= 1)
582 {
583 RunRefSize = sizeof(EX_RUNDOWN_REF);
584 }
585 else
586 {
589 ASSERT((RunRefSize & (RunRefSize - 1)) == 0);
590 }
591
592 /* It must at least hold a EX_RUNDOWN_REF structure */
593 ASSERT(sizeof(EX_RUNDOWN_REF) <= RunRefSize);
594 RunRefCacheAware->RunRefSize = RunRefSize;
595
596 /* Allocate our runref pool */
597 PoolToFree = ExAllocatePoolWithTag(PoolType, RunRefSize * RunRefCacheAware->Number, Tag);
598 if (PoolToFree == NULL)
599 {
600 ExFreePoolWithTag(RunRefCacheAware, Tag);
601 return NULL;
602 }
603
604 /* On SMP, check for alignment */
605 if (RunRefCacheAware->Number > 1 && (ULONG_PTR)PoolToFree & (Align - 1))
606 {
607 /* Not properly aligned, do it again! */
608 ExFreePoolWithTag(PoolToFree, Tag);
609
610 /* Allocate a bigger buffer to be able to align properly */
611 PoolToFree = ExAllocatePoolWithTag(PoolType, RunRefSize * (RunRefCacheAware->Number + 1), Tag);
612 if (PoolToFree == NULL)
613 {
614 ExFreePoolWithTag(RunRefCacheAware, Tag);
615 return NULL;
616 }
617
618 RunRefs = (PVOID)ALIGN_UP_BY(PoolToFree, Align);
619 }
620 else
621 {
622 RunRefs = PoolToFree;
623 }
624
625 RunRefCacheAware->RunRefs = RunRefs;
626 RunRefCacheAware->PoolToFree = PoolToFree;
627
628 /* And initialize runref */
629 if (RunRefCacheAware->Number != 0)
630 {
631 for (Count = 0; Count < RunRefCacheAware->Number; ++Count)
632 {
633 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Count);
635 }
636 }
637
638 return RunRefCacheAware;
639}
640
641/*
642 * @implemented NT5.2
643 */
644VOID
645NTAPI
647{
648 PAGED_CODE();
649
650 /*
651 * This is to be called for RunRefCacheAware that were allocated with
652 * ExAllocateCacheAwareRundownProtection and not for user-allocated
653 * ones
654 */
655 ASSERT(RunRefCacheAware->PoolToFree != (PVOID)0xBADCA11);
656
657 /* We don't know the tag that as used for allocation */
658 ExFreePoolWithTag(RunRefCacheAware->PoolToFree, 0);
659 ExFreePoolWithTag(RunRefCacheAware, 0);
660}
661
662/*
663 * @implemented NT5.2
664 */
665VOID
666NTAPI
668 IN SIZE_T Size)
669{
670 PVOID Pool;
671 PEX_RUNDOWN_REF RunRef;
673
674 PAGED_CODE();
675
676 /* Get the user allocate pool for runrefs */
677 Pool = (PVOID)((ULONG_PTR)RunRefCacheAware + sizeof(EX_RUNDOWN_REF_CACHE_AWARE));
678
679 /* By default a runref is structure-sized */
680 RunRefSize = sizeof(EX_RUNDOWN_REF);
681
682 /*
683 * If we just have enough room for a single runref, deduce were on a single
684 * processor machine
685 */
686 if (Size == sizeof(EX_RUNDOWN_REF_CACHE_AWARE) + sizeof(EX_RUNDOWN_REF))
687 {
688 Count = 1;
689 }
690 else
691 {
692 /* Get alignment constraint */
694
695 /* How many runrefs given the alignment? */
697 Count = ((Size - sizeof(EX_RUNDOWN_REF_CACHE_AWARE)) / Align) - 1;
699 }
700
701 /* Initialize the structure */
702 RunRefCacheAware->RunRefs = Pool;
703 RunRefCacheAware->RunRefSize = RunRefSize;
704 RunRefCacheAware->Number = Count;
705
706 /* There is no allocated pool! */
707 RunRefCacheAware->PoolToFree = (PVOID)0xBADCA11u;
708
709 /* Initialize runref */
710 if (RunRefCacheAware->Number != 0)
711 {
712 for (Count = 0; Count < RunRefCacheAware->Number; ++Count)
713 {
714 RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Count);
716 }
717 }
718}
719
720/*
721 * @implemented NT5.2
722 */
723SIZE_T
724NTAPI
726{
727 SIZE_T Size;
728
729 PAGED_CODE();
730
731 /* Compute the needed size for runrefs */
732 if (KeNumberProcessors <= 1)
733 {
734 Size = sizeof(EX_RUNDOWN_REF);
735 }
736 else
737 {
738 /* We +1, to have enough room for alignment */
740 }
741
742 /* Return total size (master structure and runrefs) */
743 return Size + sizeof(EX_RUNDOWN_REF_CACHE_AWARE);
744}
745
#define PAGED_CODE()
#define ALIGN_UP_BY(size, align)
unsigned char BOOLEAN
Definition: bufpool.h:50
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
int Align(int arg)
Definition: ehframes.cpp:89
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExpSetRundown(x, y)
Definition: ex.h:165
FORCEINLINE VOID _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: ex.h:904
#define ExpChangeRundown(x, y, z)
Definition: ex.h:163
FORCEINLINE BOOLEAN _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: ex.h:820
FORCEINLINE VOID _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: ex.h:861
FORCEINLINE PEX_RUNDOWN_REF ExGetRunRefForGivenProcessor(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, IN ULONG ProcNumber)
Definition: ex.h:793
#define InterlockedDecrementSizeT(a)
Definition: interlocked.h:153
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define KernelMode
Definition: asm.h:34
struct _EX_RUNDOWN_REF_CACHE_AWARE EX_RUNDOWN_REF_CACHE_AWARE
struct _EX_RUNDOWN_WAIT_BLOCK * PEX_RUNDOWN_WAIT_BLOCK
int Count
Definition: noreturn.cpp:7
#define FASTCALL
Definition: nt_native.h:50
@ SynchronizationEvent
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:710
long LONG
Definition: pedump.c:60
VOID FASTCALL ExfReInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: rundown.c:141
VOID FASTCALL ExfRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
Definition: rundown.c:169
VOID FASTCALL ExfReInitializeRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
Definition: rundown.c:534
PEX_RUNDOWN_REF_CACHE_AWARE NTAPI ExAllocateCacheAwareRundownProtection(IN POOL_TYPE PoolType, IN ULONG Tag)
Definition: rundown.c:562
BOOLEAN FASTCALL ExfAcquireRundownProtectionCacheAwareEx(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, IN ULONG Count)
Definition: rundown.c:397
VOID FASTCALL ExfWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
Definition: rundown.c:324
VOID FASTCALL ExfInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: rundown.c:118
VOID FASTCALL ExfReleaseRundownProtectionCacheAwareEx(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, IN ULONG Count)
Definition: rundown.c:424
VOID FASTCALL ExfWaitForRundownProtectionReleaseCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
Definition: rundown.c:438
BOOLEAN FASTCALL ExfAcquireRundownProtectionEx(IN PEX_RUNDOWN_REF RunRef, IN ULONG Count)
Definition: rundown.c:78
VOID NTAPI ExInitializeRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, IN SIZE_T Size)
Definition: rundown.c:667
BOOLEAN FASTCALL ExfAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: rundown.c:36
VOID NTAPI ExFreeCacheAwareRundownProtection(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
Definition: rundown.c:646
VOID FASTCALL ExfReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
Definition: rundown.c:197
SIZE_T NTAPI ExSizeOfRundownProtectionCacheAware(VOID)
Definition: rundown.c:725
BOOLEAN FASTCALL ExfAcquireRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
Definition: rundown.c:384
VOID FASTCALL ExfReleaseRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
Definition: rundown.c:411
VOID FASTCALL ExfRundownCompletedCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
Definition: rundown.c:506
VOID FASTCALL ExfReleaseRundownProtectionEx(IN PEX_RUNDOWN_REF RunRef, IN ULONG Count)
Definition: rundown.c:260
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341
PEX_RUNDOWN_REF RunRefs
Definition: extypes.h:433
volatile ULONG_PTR Count
Definition: extypes.h:181
INT POOL_TYPE
Definition: typedefs.h:78
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ SIZE_T RunRefSize
Definition: exfuncs.h:1311
#define EX_RUNDOWN_COUNT_INC
#define EX_RUNDOWN_ACTIVE
struct _EX_RUNDOWN_REF EX_RUNDOWN_REF
#define EX_RUNDOWN_COUNT_SHIFT
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ Executive
Definition: ketypes.h:415