ASSERT(WaitBlock.Count == 0);
}
-/* FIXME: STUBS **************************************************************/
-
/*
* @implemented NT5.2
*/
{
PEX_RUNDOWN_REF RunRef;
- RunRef = ExGetRunRefForCurrentProcessor(RunRefCacheAware);
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
return _ExAcquireRundownProtection(RunRef);
}
{
PEX_RUNDOWN_REF RunRef;
- RunRef = ExGetRunRefForCurrentProcessor(RunRefCacheAware);
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
return ExfAcquireRundownProtectionEx(RunRef, Count);
}
{
PEX_RUNDOWN_REF RunRef;
- RunRef = ExGetRunRefForCurrentProcessor(RunRefCacheAware);
- return _ExReleaseRundownProtection(RunRef);
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
+ _ExReleaseRundownProtection(RunRef);
}
/*
{
PEX_RUNDOWN_REF RunRef;
- RunRef = ExGetRunRefForCurrentProcessor(RunRefCacheAware);
- return ExfReleaseRundownProtectionEx(RunRef, Count);
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, KeGetCurrentProcessorNumber());
+ ExfReleaseRundownProtectionEx(RunRef, Count);
}
/*
- * @unimplemented NT5.2
+ * @implemented NT5.2
*/
VOID
FASTCALL
ExfWaitForRundownProtectionReleaseCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
{
- DBG_UNREFERENCED_PARAMETER(RunRefCacheAware);
- UNIMPLEMENTED;
+ PEX_RUNDOWN_REF RunRef;
+ EX_RUNDOWN_WAIT_BLOCK WaitBlock;
+ PEX_RUNDOWN_WAIT_BLOCK WaitBlockPointer;
+ ULONG ProcCount, Current, Value, OldValue, TotalCount;
+
+ ProcCount = RunRefCacheAware->Number;
+ /* No proc, nothing to do */
+ if (ProcCount == 0)
+ {
+ return;
+ }
+
+ TotalCount = 0;
+ WaitBlock.Count = 0;
+ WaitBlockPointer = (PEX_RUNDOWN_WAIT_BLOCK)((ULONG_PTR)&WaitBlock |
+ EX_RUNDOWN_ACTIVE);
+ /* We will check all our runrefs */
+ for (Current = 0; Current < ProcCount; ++Current)
+ {
+ /* Get the runref for the proc */
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Current);
+ /* Loop for setting the wait block */
+ do
+ {
+ Value = RunRef->Count;
+ ASSERT((Value & EX_RUNDOWN_ACTIVE) == 0);
+
+ /* Remove old value and set our waitblock instead */
+ OldValue = ExpChangeRundown(RunRef, WaitBlockPointer, Value);
+ if (OldValue == Value)
+ {
+ break;
+ }
+
+ Value = OldValue;
+ }
+ while (TRUE);
+
+ /* Count the deleted values */
+ TotalCount += Value;
+ }
+
+ /* Sanity check: we didn't overflow */
+ ASSERT((LONG)TotalCount >= 0);
+ if (TotalCount != 0)
+ {
+ /* Init the waitblock event */
+ KeInitializeEvent(&WaitBlock.WakeEvent,
+ SynchronizationEvent,
+ FALSE);
+
+ /* Do we have to wait? If so, go ahead! */
+ if (InterlockedExchangeAddSizeT(&WaitBlock.Count,
+ (LONG)TotalCount >> EX_RUNDOWN_COUNT_SHIFT) ==
+ -(LONG)(TotalCount >> EX_RUNDOWN_COUNT_SHIFT))
+ {
+ KeWaitForSingleObject(&WaitBlock.WakeEvent, Executive, KernelMode, FALSE, NULL);
+ }
+ }
}
/*
- * @unimplemented NT5.2
+ * @implemented NT5.2
*/
VOID
FASTCALL
ExfRundownCompletedCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
{
- DBG_UNREFERENCED_PARAMETER(RunRefCacheAware);
- UNIMPLEMENTED;
+ PEX_RUNDOWN_REF RunRef;
+ ULONG ProcCount, Current;
+
+ ProcCount = RunRefCacheAware->Number;
+ /* No proc, nothing to do */
+ if (ProcCount == 0)
+ {
+ return;
+ }
+
+ /* We will mark all our runrefs active */
+ for (Current = 0; Current < ProcCount; ++Current)
+ {
+ /* Get the runref for the proc */
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Current);
+ ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
+
+ ExpSetRundown(RunRef, EX_RUNDOWN_ACTIVE);
+ }
}
/*
- * @unimplemented NT5.2
+ * @implemented NT5.2
*/
VOID
FASTCALL
ExfReInitializeRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
{
- DBG_UNREFERENCED_PARAMETER(RunRefCacheAware);
- UNIMPLEMENTED;
+ PEX_RUNDOWN_REF RunRef;
+ ULONG ProcCount, Current;
+
+ ProcCount = RunRefCacheAware->Number;
+ /* No proc, nothing to do */
+ if (ProcCount == 0)
+ {
+ return;
+ }
+
+ /* We will mark all our runrefs inactive */
+ for (Current = 0; Current < ProcCount; ++Current)
+ {
+ /* Get the runref for the proc */
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Current);
+ ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
+
+ ExpSetRundown(RunRef, 0);
+ }
}
/*
{
PEX_RUNDOWN_REF RunRef;
PVOID PoolToFree, RunRefs;
- ULONG RunRefSize, Count, Offset, Align;
+ ULONG RunRefSize, Count, Align;
PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware;
PAGED_CODE();
{
for (Count = 0; Count < RunRefCacheAware->Number; ++Count)
{
- Offset = RunRefCacheAware->RunRefSize * Count;
- RunRef = (PEX_RUNDOWN_REF)((ULONG_PTR)RunRefCacheAware->RunRefs + Offset);
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Count);
_ExInitializeRundownProtection(RunRef);
}
}
{
PVOID Pool;
PEX_RUNDOWN_REF RunRef;
- ULONG Count, RunRefSize, Offset;
+ ULONG Count, RunRefSize, Align;
PAGED_CODE();
}
else
{
- /* FIXME: Properly align on SMP */
- UNIMPLEMENTED;
+ /* Get alignment constraint */
+ Align = KeGetRecommendedSharedDataAlignment();
+
+ /* How many runrefs given the alignment? */
+ RunRefSize = Align;
+ Count = ((Size - sizeof(EX_RUNDOWN_REF_CACHE_AWARE)) / Align) - 1;
+ Pool = (PVOID)ALIGN_UP_BY(Pool, Align);
}
/* Initialize the structure */
{
for (Count = 0; Count < RunRefCacheAware->Number; ++Count)
{
- Offset = RunRefCacheAware->RunRefSize * Count;
- RunRef = (PEX_RUNDOWN_REF)((ULONG_PTR)RunRefCacheAware->RunRefs + Offset);
+ RunRef = ExGetRunRefForGivenProcessor(RunRefCacheAware, Count);
_ExInitializeRundownProtection(RunRef);
}
}