[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