mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
- Implement ExCompareExchangeCallBack. The CallBack implementation is now ready for testing.
svn path=/trunk/; revision=25485
This commit is contained in:
parent
1ef7c86725
commit
b7e3f88937
1 changed files with 96 additions and 0 deletions
|
@ -37,6 +37,7 @@ SYSTEM_CALLBACKS ExpInitializeCallback[] =
|
||||||
|
|
||||||
POBJECT_TYPE ExCallbackObjectType;
|
POBJECT_TYPE ExCallbackObjectType;
|
||||||
KEVENT ExpCallbackEvent;
|
KEVENT ExpCallbackEvent;
|
||||||
|
EX_PUSH_LOCK ExpCallBackFlush;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
@ -254,6 +255,98 @@ ExDoCallBack(IN OUT PEX_CALLBACK Callback,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
ExCompareExchangeCallBack(IN OUT PEX_CALLBACK CallBack,
|
||||||
|
IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
|
||||||
|
IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock)
|
||||||
|
{
|
||||||
|
EX_FAST_REF Value, NewValue;
|
||||||
|
PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock;
|
||||||
|
PEX_FAST_REF FastRef = &CallBack->RoutineBlock;
|
||||||
|
|
||||||
|
/* Check that we have a new block */
|
||||||
|
if (NewBlock)
|
||||||
|
{
|
||||||
|
/* Acquire rundown */
|
||||||
|
if (!ExfAcquireRundownProtectionEx(&NewBlock->RundownProtect,
|
||||||
|
MAX_FAST_REFS + 1))
|
||||||
|
{
|
||||||
|
/* This should never happen */
|
||||||
|
ASSERTMSG("Callback block is already undergoing rundown", FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check and start swap loop */
|
||||||
|
ASSERT(!(((ULONG_PTR)NewBlock) & MAX_FAST_REFS));
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Get the current value */
|
||||||
|
Value = *FastRef;
|
||||||
|
|
||||||
|
/* Make sure there's enough references to swap */
|
||||||
|
if (!((Value.Value ^ (ULONG_PTR)OldBlock) <= MAX_FAST_REFS)) break;
|
||||||
|
|
||||||
|
/* Check if we have an object to swap */
|
||||||
|
if (NewBlock)
|
||||||
|
{
|
||||||
|
/* Set up the value with maximum fast references */
|
||||||
|
NewValue.Value = (ULONG_PTR)NewBlock | MAX_FAST_REFS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Write the object address itself (which is empty) */
|
||||||
|
NewValue.Value = (ULONG_PTR)NewBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the actual compare exchange */
|
||||||
|
NewValue.Object = InterlockedCompareExchangePointer(&FastRef->Object,
|
||||||
|
NewValue.Object,
|
||||||
|
Value.Object);
|
||||||
|
if (NewValue.Object != Value.Object) continue;
|
||||||
|
|
||||||
|
/* All done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the routine block */
|
||||||
|
CallbackRoutineBlock = (PVOID)(Value.Value & ~MAX_FAST_REFS);
|
||||||
|
|
||||||
|
/* Make sure the swap worked */
|
||||||
|
if (CallbackRoutineBlock == OldBlock)
|
||||||
|
{
|
||||||
|
/* Make sure we replaced a valid pointer */
|
||||||
|
if (CallbackRoutineBlock)
|
||||||
|
{
|
||||||
|
/* Acquire the flush lock and immediately release it */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
ExWaitOnPushLock(&ExpCallBackFlush);
|
||||||
|
|
||||||
|
/* Release rundown protection */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
ExfReleaseRundownProtectionEx(&CallbackRoutineBlock->RundownProtect,
|
||||||
|
Value.RefCnt + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare worked */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It failed, check if we had a block */
|
||||||
|
if (NewBlock)
|
||||||
|
{
|
||||||
|
/* We did, remove the refernces that we had added */
|
||||||
|
ExfReleaseRundownProtectionEx(&NewBlock->RundownProtect,
|
||||||
|
MAX_FAST_REFS + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return failure */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ExpDeleteCallback(IN PVOID Object)
|
ExpDeleteCallback(IN PVOID Object)
|
||||||
|
@ -287,6 +380,9 @@ ExpInitializeCallbacks(VOID)
|
||||||
HANDLE DirectoryHandle;
|
HANDLE DirectoryHandle;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
|
/* Setup lightweight callback lock */
|
||||||
|
ExpCallBackFlush.Value = 0;
|
||||||
|
|
||||||
/* Initialize the Callback Object type */
|
/* Initialize the Callback Object type */
|
||||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||||
RtlInitUnicodeString(&Name, L"Callback");
|
RtlInitUnicodeString(&Name, L"Callback");
|
||||||
|
|
Loading…
Reference in a new issue