[ros-diffs] [ion] 25484: - Implement ExReferenceCallBackBlock and ExDereferenceCallBackBlock. - Code is very similar to Ob* Fast Referencing, and the use of macros to encapsulate generic referencing should be done later. Essentially, Ob sticks ObRefs around FastRefs, while ExCallbacks sticks ExRundown around FastRefs.
ion at svn.reactos.org
ion at svn.reactos.org
Tue Jan 16 08:20:17 CET 2007
Author: ion
Date: Tue Jan 16 10:20:16 2007
New Revision: 25484
URL: http://svn.reactos.org/svn/reactos?rev=25484&view=rev
Log:
- Implement ExReferenceCallBackBlock and ExDereferenceCallBackBlock.
- Code is very similar to Ob* Fast Referencing, and the use of macros to encapsulate generic referencing should be done later. Essentially, Ob sticks ObRefs around FastRefs, while ExCallbacks sticks ExRundown around FastRefs.
Modified:
trunk/reactos/include/ddk/winddk.h
trunk/reactos/ntoskrnl/ex/callback.c
Modified: trunk/reactos/include/ddk/winddk.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/winddk.h?rev=25484&r1=25483&r2=25484&view=diff
==============================================================================
--- trunk/reactos/include/ddk/winddk.h (original)
+++ trunk/reactos/include/ddk/winddk.h Tue Jan 16 10:20:16 2007
@@ -6519,6 +6519,22 @@
IN OUT PKGUARDED_MUTEX GuardedMutex
);
+NTKERNELAPI
+BOOLEAN
+FASTCALL
+ExAcquireRundownProtectionEx(
+ IN OUT PEX_RUNDOWN_REF RunRef,
+ IN ULONG Count
+);
+
+NTKERNELAPI
+VOID
+FASTCALL
+ExReleaseRundownProtectionEx(
+ IN OUT PEX_RUNDOWN_REF RunRef,
+ IN ULONG Count
+);
+
/* Fast Mutex */
#define ExInitializeFastMutex(_FastMutex) \
{ \
Modified: trunk/reactos/ntoskrnl/ex/callback.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/callback.c?rev=25484&r1=25483&r2=25484&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ex/callback.c (original)
+++ trunk/reactos/ntoskrnl/ex/callback.c Tue Jan 16 10:20:16 2007
@@ -42,7 +42,7 @@
VOID
NTAPI
-ExInitializeCallback(IN OUT PEX_CALLBACK Callback)
+ExInitializeCallBack(IN OUT PEX_CALLBACK Callback)
{
/* Initialize the fast references */
Callback->RoutineBlock.Object = NULL;
@@ -73,7 +73,7 @@
VOID
NTAPI
-ExFreeCallback(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
+ExFreeCallBack(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
{
/* Just free it from memory */
ExFreePool(Callback);
@@ -108,15 +108,125 @@
ExDereferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack,
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock)
{
- /* FIXME: TODO */
+ PEX_FAST_REF FastRef = &CallBack->RoutineBlock;
+ EX_FAST_REF Value, NewValue;
+
+ /* Sanity checks */
+ ASSERT(CallbackRoutineBlock);
+ ASSERT(!(((ULONG_PTR)CallbackRoutineBlock) & MAX_FAST_REFS));
+
+ /* Start dereference loop */
+ for (;;)
+ {
+ /* Get the current count */
+ Value = *FastRef;
+ if ((Value.Value ^ (ULONG_PTR)CallbackRoutineBlock) < MAX_FAST_REFS)
+ {
+ /* Decrease the reference count */
+ NewValue.Value = Value.Value + 1;
+ NewValue.Object = InterlockedCompareExchangePointer(&FastRef->Object,
+ NewValue.Object,
+ Value.Object);
+ if (NewValue.Object != Value.Object) continue;
+
+ /* We're all done */
+ break;
+ }
+ else
+ {
+ /* Release rundown protection */
+ ExReleaseRundownProtection(&CallbackRoutineBlock->RundownProtect);
+ }
+ }
}
PEX_CALLBACK_ROUTINE_BLOCK
NTAPI
ExReferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack)
{
- /* FIXME: TODO */
- return NULL;
+ PEX_FAST_REF FastRef = &CallBack->RoutineBlock;
+ EX_FAST_REF Value, NewValue;
+ PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock;
+
+ /* Start reference loop */
+ for (;;)
+ {
+ /* Get the current count */
+ Value = *FastRef;
+ if (Value.RefCnt != 0)
+ {
+ /* Increase the reference count */
+ NewValue.Value = Value.Value - 1;
+ NewValue.Object = InterlockedCompareExchangePointer(&FastRef->Object,
+ NewValue.Object,
+ Value.Object);
+ if (NewValue.Object != Value.Object) continue;
+ }
+
+ /* All done */
+ break;
+ }
+
+ /* Fail if there isn't any object */
+ if (!Value.Value) return NULL;
+
+ /* Check if we don't have a reference */
+ if (!Value.RefCnt)
+ {
+ /* FIXME: Race */
+ CallbackRoutineBlock = NULL;
+ DPRINT1("Unhandled callback race condition\n");
+ KEBUGCHECK(0);
+ }
+ else
+ {
+ /* Get the callback block */
+ CallbackRoutineBlock = (PVOID)(Value.Value &~ MAX_FAST_REFS);
+
+ /* Check if this is the last reference */
+ if (Value.RefCnt == 1)
+ {
+ /* Acquire rundown protection */
+ if (ExfAcquireRundownProtectionEx(&CallbackRoutineBlock->
+ RundownProtect,
+ MAX_FAST_REFS))
+ {
+ /* Sanity check */
+ ASSERT(!(((ULONG_PTR)CallbackRoutineBlock) & MAX_FAST_REFS));
+
+ /* Start reference loop */
+ for (;;)
+ {
+ /* Check if the current count is too high */
+ Value = *FastRef;
+ if (((Value.RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
+ ((Value.Value &~ MAX_FAST_REFS) !=
+ (ULONG_PTR)CallbackRoutineBlock))
+ {
+ /* Backdown the rundown acquire */
+ ExfReleaseRundownProtectionEx(&CallbackRoutineBlock->
+ RundownProtect,
+ MAX_FAST_REFS);
+ break;
+ }
+
+ /* Increase the reference count */
+ NewValue.Value = Value.Value + MAX_FAST_REFS;
+ NewValue.Object =
+ InterlockedCompareExchangePointer(&FastRef->Object,
+ NewValue.Object,
+ Value.Object);
+ if (NewValue.Object != Value.Object) continue;
+
+ /* Break out if the change was OK */
+ break;
+ }
+ }
+ }
+ }
+
+ /* Return the callback block */
+ return CallbackRoutineBlock;
}
VOID
More information about the Ros-diffs
mailing list