mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
fixed some bugs in ExWaitForRundownProtectionRelease() and ExReleaseRundownProtectionEx()
svn path=/trunk/; revision=13699
This commit is contained in:
parent
96969f6dc7
commit
502d8150de
1 changed files with 47 additions and 38 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id:$
|
/* $Id$
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -118,23 +118,27 @@ ExReleaseRundownProtectionEx (
|
||||||
/* Get Pointer */
|
/* Get Pointer */
|
||||||
PRUNDOWN_DESCRIPTOR RundownDescriptor = (PRUNDOWN_DESCRIPTOR)((ULONG_PTR)RunRef->Ptr & ~EX_RUNDOWN_ACTIVE);
|
PRUNDOWN_DESCRIPTOR RundownDescriptor = (PRUNDOWN_DESCRIPTOR)((ULONG_PTR)RunRef->Ptr & ~EX_RUNDOWN_ACTIVE);
|
||||||
|
|
||||||
/* Decrease Reference Count by RundownDescriptor->References */
|
ASSERT(RundownDescriptor != NULL);
|
||||||
|
|
||||||
|
Current = RundownDescriptor->References;
|
||||||
|
|
||||||
|
/* Decrease RundownDescriptor->References by Count references */
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
ULONG_PTR PrevCount, NewCount;
|
ULONG_PTR PrevCount, NewCount;
|
||||||
|
|
||||||
if ((Current >> EX_RUNDOWN_COUNT_SHIFT) == RundownDescriptor->References)
|
if ((Count >> EX_RUNDOWN_COUNT_SHIFT) == Current)
|
||||||
{
|
{
|
||||||
NewCount = 0;
|
NewCount = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NewCount = (((Current >> EX_RUNDOWN_COUNT_SHIFT) - RundownDescriptor->References) << EX_RUNDOWN_COUNT_SHIFT) | EX_RUNDOWN_ACTIVE;
|
NewCount = ((RundownDescriptor->References - (Count >> EX_RUNDOWN_COUNT_SHIFT)) << EX_RUNDOWN_COUNT_SHIFT) | EX_RUNDOWN_ACTIVE;
|
||||||
}
|
}
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
PrevCount = (ULONG_PTR)InterlockedCompareExchange64((LONGLONG*)&RunRef->Count, (LONGLONG)NewCount, (LONGLONG)Current);
|
PrevCount = (ULONG_PTR)InterlockedCompareExchange64((LONGLONG*)&RundownDescriptor->References, (LONGLONG)NewCount, (LONGLONG)Current);
|
||||||
#else
|
#else
|
||||||
PrevCount = (ULONG_PTR)InterlockedCompareExchange((LONG*)&RunRef->Count, (LONG)NewCount, (LONG)Current);
|
PrevCount = (ULONG_PTR)InterlockedCompareExchange((LONG*)&RundownDescriptor->References, (LONG)NewCount, (LONG)Current);
|
||||||
#endif
|
#endif
|
||||||
if (PrevCount == Current)
|
if (PrevCount == Current)
|
||||||
{
|
{
|
||||||
|
@ -212,40 +216,45 @@ ExWaitForRundownProtectionRelease (
|
||||||
ULONG_PTR PrevCount, NewPtr, PrevPtr;
|
ULONG_PTR PrevCount, NewPtr, PrevPtr;
|
||||||
RUNDOWN_DESCRIPTOR RundownDescriptor;
|
RUNDOWN_DESCRIPTOR RundownDescriptor;
|
||||||
|
|
||||||
#ifdef _WIN64
|
PrevCount = RunRef->Count;
|
||||||
PrevCount = (ULONG_PTR)InterlockedCompareExchange64((LONGLONG*)&RunRef->Ptr, (LONGLONG)EX_RUNDOWN_ACTIVE, 0LL);
|
|
||||||
#else
|
|
||||||
PrevCount = (ULONG_PTR)InterlockedCompareExchange((LONG*)&RunRef->Ptr, EX_RUNDOWN_ACTIVE, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (PrevCount == 0 ||
|
if (PrevCount != 0 && !(PrevCount & EX_RUNDOWN_ACTIVE))
|
||||||
PrevCount & EX_RUNDOWN_ACTIVE)
|
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the reference counter */
|
/* save the reference counter */
|
||||||
RundownDescriptor.References = PrevCount >> EX_RUNDOWN_COUNT_SHIFT;
|
RundownDescriptor.References = PrevCount >> EX_RUNDOWN_COUNT_SHIFT;
|
||||||
|
|
||||||
/* Pending references... wait on them to be closed with an event */
|
/* Pending references... wait on them to be closed with an event */
|
||||||
KeInitializeEvent(&RundownDescriptor.RundownEvent, NotificationEvent, FALSE);
|
KeInitializeEvent(&RundownDescriptor.RundownEvent, NotificationEvent, FALSE);
|
||||||
|
|
||||||
NewPtr = (ULONG_PTR)&RundownDescriptor | EX_RUNDOWN_ACTIVE;
|
ASSERT(!((ULONG_PTR)&RundownDescriptor & EX_RUNDOWN_ACTIVE));
|
||||||
PrevCount = EX_RUNDOWN_ACTIVE;
|
|
||||||
|
|
||||||
do
|
NewPtr = (ULONG_PTR)&RundownDescriptor | EX_RUNDOWN_ACTIVE;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
PrevPtr = (ULONG_PTR)InterlockedCompareExchange64((LONGLONG*)&RunRef->Ptr, (LONGLONG)NewPtr, (LONGLONG)PrevCount);
|
PrevPtr = (ULONG_PTR)InterlockedCompareExchange64((LONGLONG*)&RunRef->Ptr, (LONGLONG)NewPtr, (LONGLONG)PrevCount);
|
||||||
#else
|
#else
|
||||||
PrevPtr = (ULONG_PTR)InterlockedCompareExchange((LONG*)&RunRef->Ptr, (LONG)NewPtr, (LONG)PrevCount);
|
PrevPtr = (ULONG_PTR)InterlockedCompareExchange((LONG*)&RunRef->Ptr, (LONG)NewPtr, (LONG)PrevCount);
|
||||||
#endif
|
#endif
|
||||||
|
if (PrevPtr == PrevCount)
|
||||||
PrevCount = PrevPtr;
|
{
|
||||||
} while (PrevPtr != PrevCount);
|
|
||||||
|
|
||||||
/* Wait for whoever needs to release to notify us */
|
/* Wait for whoever needs to release to notify us */
|
||||||
KeWaitForSingleObject(&RundownDescriptor.RundownEvent, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&RundownDescriptor.RundownEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (PrevPtr == 0 || (PrevPtr & EX_RUNDOWN_ACTIVE))
|
||||||
|
{
|
||||||
|
/* some one else was faster, let's just bail */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrevCount = PrevPtr;
|
||||||
|
|
||||||
|
/* save the changed reference counter and try again */
|
||||||
|
RundownDescriptor.References = PrevCount >> EX_RUNDOWN_COUNT_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue