Reduce code duplication in rundown protection
This commit is contained in:
@@ -24,38 +24,8 @@ XTFASTCALL
|
|||||||
BOOLEAN
|
BOOLEAN
|
||||||
EX::Rundown::AcquireProtection(IN PEX_RUNDOWN_REFERENCE Descriptor)
|
EX::Rundown::AcquireProtection(IN PEX_RUNDOWN_REFERENCE Descriptor)
|
||||||
{
|
{
|
||||||
ULONG_PTR CurrentValue, NewValue;
|
/* Acquire protection */
|
||||||
|
return AcquireProtection(Descriptor, 1);
|
||||||
/* Get current value */
|
|
||||||
CurrentValue = Descriptor->Count;
|
|
||||||
|
|
||||||
/* Main loop execution */
|
|
||||||
while(TRUE)
|
|
||||||
{
|
|
||||||
/* Make sure protection is not active yet */
|
|
||||||
if(CurrentValue & 0x1)
|
|
||||||
{
|
|
||||||
/* Already active, nothing to do */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attempt to increment the usage count */
|
|
||||||
NewValue = CurrentValue + 2;
|
|
||||||
|
|
||||||
/* Exchange the value */
|
|
||||||
NewValue = (ULONG_PTR)RTL::Atomic::CompareExchangePointer(&Descriptor->Ptr, (PVOID)NewValue,
|
|
||||||
(PVOID)CurrentValue);
|
|
||||||
|
|
||||||
/* Make sure protection acquired */
|
|
||||||
if(NewValue == CurrentValue)
|
|
||||||
{
|
|
||||||
/* Successfully acquired protection */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update value and try once again */
|
|
||||||
CurrentValue = NewValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,51 +148,8 @@ XTFASTCALL
|
|||||||
VOID
|
VOID
|
||||||
EX::Rundown::ReleaseProtection(IN PEX_RUNDOWN_REFERENCE Descriptor)
|
EX::Rundown::ReleaseProtection(IN PEX_RUNDOWN_REFERENCE Descriptor)
|
||||||
{
|
{
|
||||||
ULONG_PTR CurrentValue, NewValue;
|
/* Release protection */
|
||||||
PEX_RUNDOWN_WAIT_BLOCK WaitBlock;
|
ReleaseProtection(Descriptor, 1);
|
||||||
|
|
||||||
/* Read the current state of the rundown descriptor */
|
|
||||||
CurrentValue = Descriptor->Count;
|
|
||||||
|
|
||||||
/* Enter a CAS loop */
|
|
||||||
while(TRUE)
|
|
||||||
{
|
|
||||||
/* Check if the rundown is currently active */
|
|
||||||
if(CurrentValue & 0x1)
|
|
||||||
{
|
|
||||||
/* Extract the pointer to the wait block */
|
|
||||||
WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(CurrentValue & ~0x1);
|
|
||||||
|
|
||||||
/* Decrement the pending reference count */
|
|
||||||
if(!RTL::Atomic::Decrement64((PLONG_PTR)&WaitBlock->Count))
|
|
||||||
{
|
|
||||||
/* Signal the event to wake up the teardown thread */
|
|
||||||
KE::Event::SetEvent(&WaitBlock->WakeEvent, 0, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Break the loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Attempt to decrement the usage count */
|
|
||||||
NewValue = CurrentValue - 2;
|
|
||||||
|
|
||||||
/* Exchange the value */
|
|
||||||
NewValue = (ULONG_PTR)RTL::Atomic::CompareExchangePointer(&Descriptor->Ptr, (PVOID)NewValue,
|
|
||||||
(PVOID)CurrentValue);
|
|
||||||
|
|
||||||
/* Check if the atomic swap succeeded without interference from other processors */
|
|
||||||
if(NewValue == CurrentValue)
|
|
||||||
{
|
|
||||||
/* Reference count is decremented, break the loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Collision detected, update current state and retry */
|
|
||||||
CurrentValue = NewValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user