[ros-diffs] [fireball] 39859: - Refactor Fast Reference implementation into a generic module with init/acquire/release/compare/insert interfaces, and update the executive callback & object manager referencing code to use it. - Always capture fast reference values on the stack since a fast reference is by nature volatile. - Based off earlier work from Alex to fix callback implementation.

fireball at svn.reactos.org fireball at svn.reactos.org
Tue Mar 3 21:24:11 CET 2009


Author: fireball
Date: Tue Mar  3 23:24:10 2009
New Revision: 39859

URL: http://svn.reactos.org/svn/reactos?rev=39859&view=rev
Log:
- Refactor Fast Reference implementation into a generic module with init/acquire/release/compare/insert interfaces, and update the executive callback & object manager referencing code to use it.
- Always capture fast reference values on the stack since a fast reference is by nature volatile.
- Based off earlier work from Alex to fix callback implementation.

Modified:
    trunk/reactos/ntoskrnl/ex/callback.c
    trunk/reactos/ntoskrnl/include/internal/ex.h
    trunk/reactos/ntoskrnl/ob/obref.c

Modified: trunk/reactos/ntoskrnl/ex/callback.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/callback.c?rev=39859&r1=39858&r2=39859&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ex/callback.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/callback.c [iso-8859-1] Tue Mar  3 23:24:10 2009
@@ -45,8 +45,8 @@
 NTAPI
 ExInitializeCallBack(IN OUT PEX_CALLBACK Callback)
 {
-    /* Initialize the fast references */
-    Callback->RoutineBlock.Object = NULL;
+    /* Initialize the fast reference */
+    ExInitializeFastReference(&Callback->RoutineBlock, NULL);
 }
 
 PEX_CALLBACK_ROUTINE_BLOCK
@@ -54,93 +54,66 @@
 ExAllocateCallBack(IN PEX_CALLBACK_FUNCTION Function,
                    IN PVOID Context)
 {
-    PEX_CALLBACK_ROUTINE_BLOCK Callback;
+    PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
 
     /* Allocate a callback */
-    Callback = ExAllocatePoolWithTag(PagedPool,
-                                     sizeof(*Callback),
-                                     TAG('C', 'b', 'r', 'b'));
-    if (Callback)
+    CallbackBlock = ExAllocatePoolWithTag(PagedPool,
+                                          sizeof(EX_CALLBACK_ROUTINE_BLOCK),
+                                          'CbRb');
+    if (CallbackBlock)
     {
         /* Initialize it */
-        Callback->Function = Function;
-        Callback->Context = Context;
-        ExInitializeRundownProtection(&Callback->RundownProtect);
+        CallbackBlock->Function = Function;
+        CallbackBlock->Context = Context;
+        ExInitializeRundownProtection(&CallbackBlock->RundownProtect);
     }
 
     /* Return it */
-    return Callback;
+    return CallbackBlock;
 }
 
 VOID
 NTAPI
-ExFreeCallBack(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
+ExFreeCallBack(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
 {
     /* Just free it from memory */
-    ExFreePool(Callback);
+    ExFreePool(CallbackBlock);
 }
 
 VOID
 NTAPI
-ExWaitForCallBacks(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
+ExWaitForCallBacks(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
 {
     /* Wait on the rundown */
-    ExWaitForRundownProtectionRelease(&Callback->RundownProtect);
+    ExWaitForRundownProtectionRelease(&CallbackBlock->RundownProtect);
 }
 
 PEX_CALLBACK_FUNCTION
 NTAPI
-ExGetCallBackBlockRoutine(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
+ExGetCallBackBlockRoutine(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
 {
     /* Return the function */
-    return Callback->Function;
+    return CallbackBlock->Function;
 }
 
 PVOID
 NTAPI
-ExGetCallBackBlockContext(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
+ExGetCallBackBlockContext(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
 {
     /* Return the context */
-    return Callback->Context;
+    return CallbackBlock->Context;
 }
 
 VOID
 NTAPI
 ExDereferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack,
-                           IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock)
-{
-    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);
-
-            /* We're all done */
-            break;
-        }
+                           IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
+{
+    /* Release a fast reference */
+    if (!ExReleaseFastReference(&CallBack->RoutineBlock, CallbackBlock))
+    {
+        /* Take slow path */
+        ExReleaseRundownProtection(&CallbackBlock->RundownProtect);
     }
 }
 
@@ -148,89 +121,48 @@
 NTAPI
 ExReferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack)
 {
-    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;
-    }
+    EX_FAST_REF OldValue;
+    ULONG_PTR Count;
+    PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
+    
+    /* Acquire a reference */
+    OldValue = ExAcquireFastReference(&CallBack->RoutineBlock);
+    Count = ExGetCountFastReference(OldValue);
 
     /* Fail if there isn't any object */
-    if (!Value.Value) return NULL;
+    if (!ExGetObjectFastReference(OldValue)) return NULL;
 
     /* Check if we don't have a reference */
-    if (!Value.RefCnt)
+    if (!Count)
     {
         /* FIXME: Race */
-        CallbackRoutineBlock = NULL;
         DPRINT1("Unhandled callback race condition\n");
         ASSERT(FALSE);
-    }
-    else
-    {
-        /* Get the callback block */
-        CallbackRoutineBlock = (PVOID)(Value.Value &~ MAX_FAST_REFS);
-
-        /* Check if this is the last reference */
-        if (Value.RefCnt == 1)
+        return NULL;
+    }
+    
+    /* Get the callback block */
+    CallbackBlock = ExGetObjectFastReference(OldValue);
+    
+    /* Check if this is the last reference */
+    if (Count == 1)
+    {
+        /* Acquire rundown protection */
+        if (ExfAcquireRundownProtectionEx(&CallbackBlock->RundownProtect,
+                                          MAX_FAST_REFS))
         {
-            /* Acquire rundown protection */
-            if (ExfAcquireRundownProtectionEx(&CallbackRoutineBlock->
-                                              RundownProtect,
-                                              MAX_FAST_REFS))
+            /* Insert references */
+            if (!ExInsertFastReference(&CallBack->RoutineBlock, CallbackBlock))
             {
-                /* 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;
-                }
+                /* Backdown the rundown acquire */
+                ExfReleaseRundownProtectionEx(&CallbackBlock->RundownProtect,
+                                              MAX_FAST_REFS);
             }
         }
     }
 
     /* Return the callback block */
-    return CallbackRoutineBlock;
+    return CallbackBlock;
 }
 
 BOOLEAN
@@ -239,9 +171,9 @@
                           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;
+    EX_FAST_REF OldValue;
+    PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
+    ULONG_PTR Count;
 
     /* Check that we have a new block */
     if (NewBlock)
@@ -255,47 +187,21 @@
             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;
-    }
+    
+    /* Do the swap */
+    OldValue = ExCompareSwapFastReference(&CallBack->RoutineBlock,
+                                          NewBlock,
+                                          OldBlock);
 
     /* Get the routine block */
-    CallbackRoutineBlock = (PVOID)(Value.Value & ~MAX_FAST_REFS);
+    CallbackBlock = ExGetObjectFastReference(OldValue);
+    Count = ExGetCountFastReference(OldValue);
 
     /* Make sure the swap worked */
-    if (CallbackRoutineBlock == OldBlock)
+    if (CallbackBlock == OldBlock)
     {
         /* Make sure we replaced a valid pointer */
-        if (CallbackRoutineBlock)
+        if (CallbackBlock)
         {
             /* Acquire the flush lock and immediately release it */
             KeEnterCriticalRegion();
@@ -303,8 +209,8 @@
 
             /* Release rundown protection */
             KeLeaveCriticalRegion();
-            ExfReleaseRundownProtectionEx(&CallbackRoutineBlock->RundownProtect,
-                                          Value.RefCnt + 1);
+            ExfReleaseRundownProtectionEx(&CallbackBlock->RundownProtect,
+                                          Count + 1);
         }
 
         /* Compare worked */

Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ex.h?rev=39859&r1=39858&r2=39859&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] Tue Mar  3 23:24:10 2009
@@ -119,346 +119,6 @@
 
 #endif
 
-/* INITIALIZATION FUNCTIONS *************************************************/
-
-VOID
-NTAPI
-ExpWin32kInit(VOID);
-
-VOID
-NTAPI
-ExInit2(VOID);
-
-VOID
-NTAPI
-Phase1Initialization(
-    IN PVOID Context
-);
-
-VOID
-NTAPI
-ExpInitializePushLocks(VOID);
-
-BOOLEAN
-NTAPI
-ExRefreshTimeZoneInformation(
-    IN PLARGE_INTEGER SystemBootTime
-);
-
-VOID
-NTAPI
-ExpInitializeWorkerThreads(VOID);
-
-VOID
-NTAPI
-ExpInitLookasideLists(VOID);
-
-VOID
-NTAPI
-ExInitializeSystemLookasideList(
-    IN PGENERAL_LOOKASIDE List,
-    IN POOL_TYPE Type,
-    IN ULONG Size,
-    IN ULONG Tag,
-    IN USHORT MaximumDepth,
-    IN PLIST_ENTRY ListHead
-);
-
-BOOLEAN
-NTAPI
-ExpInitializeCallbacks(VOID);
-
-VOID
-NTAPI
-ExpInitUuids(VOID);
-
-VOID
-NTAPI
-ExpInitializeExecutive(
-    IN ULONG Cpu,
-    IN PLOADER_PARAMETER_BLOCK LoaderBlock
-);
-
-VOID
-NTAPI
-ExpInitializeEventImplementation(VOID);
-
-VOID
-NTAPI
-ExpInitializeEventImplementation(VOID);
-
-VOID
-NTAPI
-ExpInitializeEventPairImplementation(VOID);
-
-VOID
-NTAPI
-ExpInitializeSemaphoreImplementation(VOID);
-
-VOID
-NTAPI
-ExpInitializeMutantImplementation(VOID);
-
-VOID
-NTAPI
-ExpInitializeTimerImplementation(VOID);
-
-VOID
-NTAPI
-ExpInitializeProfileImplementation(VOID);
-
-VOID
-NTAPI
-ExpResourceInitialization(VOID);
-
-VOID
-NTAPI
-ExInitPoolLookasidePointers(VOID);
-
-/* Callback Functions ********************************************************/
-
-VOID
-NTAPI
-ExInitializeCallBack(
-    IN OUT PEX_CALLBACK Callback
-);
-
-PEX_CALLBACK_ROUTINE_BLOCK
-NTAPI
-ExAllocateCallBack(
-    IN PEX_CALLBACK_FUNCTION Function,
-    IN PVOID Context
-);
-
-VOID
-NTAPI
-ExFreeCallBack(
-    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
-);
-
-BOOLEAN
-NTAPI
-ExCompareExchangeCallBack (
-    IN OUT PEX_CALLBACK CallBack,
-    IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
-    IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
-);
-
-PEX_CALLBACK_ROUTINE_BLOCK
-NTAPI
-ExReferenceCallBackBlock(
-    IN OUT PEX_CALLBACK CallBack
-);
-
-VOID
-NTAPI
-ExDereferenceCallBackBlock(
-    IN OUT PEX_CALLBACK CallBack,
-    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
-);
-
-PEX_CALLBACK_FUNCTION
-NTAPI
-ExGetCallBackBlockRoutine(
-    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
-);
-
-PVOID
-NTAPI
-ExGetCallBackBlockContext(
-    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
-);
-
-VOID
-NTAPI
-ExWaitForCallBacks(
-    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
-);
-
-/* Rundown Functions ********************************************************/
-
-VOID
-FASTCALL
-ExfInitializeRundownProtection(
-     OUT PEX_RUNDOWN_REF RunRef
-);
-
-VOID
-FASTCALL
-ExfReInitializeRundownProtection(
-     OUT PEX_RUNDOWN_REF RunRef
-);
-
-BOOLEAN
-FASTCALL
-ExfAcquireRundownProtection(
-     IN OUT PEX_RUNDOWN_REF RunRef
-);
-
-BOOLEAN
-FASTCALL
-ExfAcquireRundownProtectionEx(
-     IN OUT PEX_RUNDOWN_REF RunRef,
-     IN ULONG Count
-);
-
-VOID
-FASTCALL
-ExfReleaseRundownProtection(
-     IN OUT PEX_RUNDOWN_REF RunRef
-);
-
-VOID
-FASTCALL
-ExfReleaseRundownProtectionEx(
-     IN OUT PEX_RUNDOWN_REF RunRef,
-     IN ULONG Count
-);
-
-VOID
-FASTCALL
-ExfRundownCompleted(
-     OUT PEX_RUNDOWN_REF RunRef
-);
-
-VOID
-FASTCALL
-ExfWaitForRundownProtectionRelease(
-     IN OUT PEX_RUNDOWN_REF RunRef
-);
-
-/* HANDLE TABLE FUNCTIONS ***************************************************/
-
-typedef BOOLEAN
-(NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
-    PHANDLE_TABLE_ENTRY HandleTableEntry,
-    HANDLE Handle,
-    PVOID Context
-);
-
-typedef BOOLEAN
-(NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
-    IN PEPROCESS Process,
-    IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
-    IN PHANDLE_TABLE_ENTRY NewEntry
-);
-
-typedef BOOLEAN
-(NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
-    PHANDLE_TABLE_ENTRY HandleTableEntry,
-    ULONG_PTR Context
-);
-
-VOID
-NTAPI
-ExpInitializeHandleTables(
-    VOID
-);
-
-PHANDLE_TABLE
-NTAPI
-ExCreateHandleTable(
-    IN PEPROCESS Process OPTIONAL
-);
-
-VOID
-NTAPI
-ExUnlockHandleTableEntry(
-    IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY HandleTableEntry
-);
-
-HANDLE
-NTAPI
-ExCreateHandle(
-    IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY HandleTableEntry
-);
-
-VOID
-NTAPI
-ExDestroyHandleTable(
-    IN PHANDLE_TABLE HandleTable,
-    IN PVOID DestroyHandleProcedure OPTIONAL
-);
-
-BOOLEAN
-NTAPI
-ExDestroyHandle(
-    IN PHANDLE_TABLE HandleTable,
-    IN HANDLE Handle,
-    IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
-);
-
-PHANDLE_TABLE_ENTRY
-NTAPI
-ExMapHandleToPointer(
-    IN PHANDLE_TABLE HandleTable,
-    IN HANDLE Handle
-);
-
-PHANDLE_TABLE
-NTAPI
-ExDupHandleTable(
-    IN PEPROCESS Process,
-    IN PHANDLE_TABLE HandleTable,
-    IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
-    IN ULONG_PTR Mask
-);
-
-BOOLEAN
-NTAPI
-ExChangeHandle(
-    IN PHANDLE_TABLE HandleTable,
-    IN HANDLE Handle,
-    IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
-    IN ULONG_PTR Context
-);
-
-VOID
-NTAPI
-ExSweepHandleTable(
-    IN PHANDLE_TABLE HandleTable,
-    IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
-    IN PVOID Context
-);
-
-/* PSEH EXCEPTION HANDLING **************************************************/
-
-LONG
-NTAPI
-ExSystemExceptionFilter(VOID);
-
-/* CALLBACKS *****************************************************************/
-
-FORCEINLINE
-VOID
-ExDoCallBack(IN OUT PEX_CALLBACK Callback,
-             IN PVOID Context,
-             IN PVOID Argument1,
-             IN PVOID Argument2)
-{
-    PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock;
-    PEX_CALLBACK_FUNCTION Function;
-
-    /* Reference the block */
-    CallbackRoutineBlock = ExReferenceCallBackBlock(Callback);
-    if (CallbackRoutineBlock)
-    {
-        /* Get the function */
-        Function = ExGetCallBackBlockRoutine(CallbackRoutineBlock);
-
-        /* Do the callback */
-        Function(Context, Argument1, Argument2);
-
-        /* Now dereference it */
-        ExDereferenceCallBackBlock(Callback, CallbackRoutineBlock);
-    }
-}
-
-/* RUNDOWN *******************************************************************/
-
 #ifdef _WIN64
 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
@@ -467,6 +127,559 @@
 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
 #endif
+
+/* INITIALIZATION FUNCTIONS *************************************************/
+
+VOID
+NTAPI
+ExpWin32kInit(VOID);
+
+VOID
+NTAPI
+ExInit2(VOID);
+
+VOID
+NTAPI
+Phase1Initialization(
+    IN PVOID Context
+);
+
+VOID
+NTAPI
+ExpInitializePushLocks(VOID);
+
+BOOLEAN
+NTAPI
+ExRefreshTimeZoneInformation(
+    IN PLARGE_INTEGER SystemBootTime
+);
+
+VOID
+NTAPI
+ExpInitializeWorkerThreads(VOID);
+
+VOID
+NTAPI
+ExpInitLookasideLists(VOID);
+
+VOID
+NTAPI
+ExInitializeSystemLookasideList(
+    IN PGENERAL_LOOKASIDE List,
+    IN POOL_TYPE Type,
+    IN ULONG Size,
+    IN ULONG Tag,
+    IN USHORT MaximumDepth,
+    IN PLIST_ENTRY ListHead
+);
+
+BOOLEAN
+NTAPI
+ExpInitializeCallbacks(VOID);
+
+VOID
+NTAPI
+ExpInitUuids(VOID);
+
+VOID
+NTAPI
+ExpInitializeExecutive(
+    IN ULONG Cpu,
+    IN PLOADER_PARAMETER_BLOCK LoaderBlock
+);
+
+VOID
+NTAPI
+ExpInitializeEventImplementation(VOID);
+
+VOID
+NTAPI
+ExpInitializeEventImplementation(VOID);
+
+VOID
+NTAPI
+ExpInitializeEventPairImplementation(VOID);
+
+VOID
+NTAPI
+ExpInitializeSemaphoreImplementation(VOID);
+
+VOID
+NTAPI
+ExpInitializeMutantImplementation(VOID);
+
+VOID
+NTAPI
+ExpInitializeTimerImplementation(VOID);
+
+VOID
+NTAPI
+ExpInitializeProfileImplementation(VOID);
+
+VOID
+NTAPI
+ExpResourceInitialization(VOID);
+
+VOID
+NTAPI
+ExInitPoolLookasidePointers(VOID);
+
+/* Callback Functions ********************************************************/
+
+VOID
+NTAPI
+ExInitializeCallBack(
+    IN OUT PEX_CALLBACK Callback
+);
+
+PEX_CALLBACK_ROUTINE_BLOCK
+NTAPI
+ExAllocateCallBack(
+    IN PEX_CALLBACK_FUNCTION Function,
+    IN PVOID Context
+);
+
+VOID
+NTAPI
+ExFreeCallBack(
+    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
+);
+
+BOOLEAN
+NTAPI
+ExCompareExchangeCallBack (
+    IN OUT PEX_CALLBACK CallBack,
+    IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
+    IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
+);
+
+PEX_CALLBACK_ROUTINE_BLOCK
+NTAPI
+ExReferenceCallBackBlock(
+    IN OUT PEX_CALLBACK CallBack
+);
+
+VOID
+NTAPI
+ExDereferenceCallBackBlock(
+    IN OUT PEX_CALLBACK CallBack,
+    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
+);
+
+PEX_CALLBACK_FUNCTION
+NTAPI
+ExGetCallBackBlockRoutine(
+    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
+);
+
+PVOID
+NTAPI
+ExGetCallBackBlockContext(
+    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
+);
+
+VOID
+NTAPI
+ExWaitForCallBacks(
+    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
+);
+
+/* Rundown Functions ********************************************************/
+
+VOID
+FASTCALL
+ExfInitializeRundownProtection(
+     OUT PEX_RUNDOWN_REF RunRef
+);
+
+VOID
+FASTCALL
+ExfReInitializeRundownProtection(
+     OUT PEX_RUNDOWN_REF RunRef
+);
+
+BOOLEAN
+FASTCALL
+ExfAcquireRundownProtection(
+     IN OUT PEX_RUNDOWN_REF RunRef
+);
+
+BOOLEAN
+FASTCALL
+ExfAcquireRundownProtectionEx(
+     IN OUT PEX_RUNDOWN_REF RunRef,
+     IN ULONG Count
+);
+
+VOID
+FASTCALL
+ExfReleaseRundownProtection(
+     IN OUT PEX_RUNDOWN_REF RunRef
+);
+
+VOID
+FASTCALL
+ExfReleaseRundownProtectionEx(
+     IN OUT PEX_RUNDOWN_REF RunRef,
+     IN ULONG Count
+);
+
+VOID
+FASTCALL
+ExfRundownCompleted(
+     OUT PEX_RUNDOWN_REF RunRef
+);
+
+VOID
+FASTCALL
+ExfWaitForRundownProtectionRelease(
+     IN OUT PEX_RUNDOWN_REF RunRef
+);
+
+/* HANDLE TABLE FUNCTIONS ***************************************************/
+
+typedef BOOLEAN
+(NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
+    PHANDLE_TABLE_ENTRY HandleTableEntry,
+    HANDLE Handle,
+    PVOID Context
+);
+
+typedef BOOLEAN
+(NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
+    IN PEPROCESS Process,
+    IN PHANDLE_TABLE HandleTable,
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
+    IN PHANDLE_TABLE_ENTRY NewEntry
+);
+
+typedef BOOLEAN
+(NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
+    PHANDLE_TABLE_ENTRY HandleTableEntry,
+    ULONG_PTR Context
+);
+
+VOID
+NTAPI
+ExpInitializeHandleTables(
+    VOID
+);
+
+PHANDLE_TABLE
+NTAPI
+ExCreateHandleTable(
+    IN PEPROCESS Process OPTIONAL
+);
+
+VOID
+NTAPI
+ExUnlockHandleTableEntry(
+    IN PHANDLE_TABLE HandleTable,
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry
+);
+
+HANDLE
+NTAPI
+ExCreateHandle(
+    IN PHANDLE_TABLE HandleTable,
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry
+);
+
+VOID
+NTAPI
+ExDestroyHandleTable(
+    IN PHANDLE_TABLE HandleTable,
+    IN PVOID DestroyHandleProcedure OPTIONAL
+);
+
+BOOLEAN
+NTAPI
+ExDestroyHandle(
+    IN PHANDLE_TABLE HandleTable,
+    IN HANDLE Handle,
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
+);
+
+PHANDLE_TABLE_ENTRY
+NTAPI
+ExMapHandleToPointer(
+    IN PHANDLE_TABLE HandleTable,
+    IN HANDLE Handle
+);
+
+PHANDLE_TABLE
+NTAPI
+ExDupHandleTable(
+    IN PEPROCESS Process,
+    IN PHANDLE_TABLE HandleTable,
+    IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
+    IN ULONG_PTR Mask
+);
+
+BOOLEAN
+NTAPI
+ExChangeHandle(
+    IN PHANDLE_TABLE HandleTable,
+    IN HANDLE Handle,
+    IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
+    IN ULONG_PTR Context
+);
+
+VOID
+NTAPI
+ExSweepHandleTable(
+    IN PHANDLE_TABLE HandleTable,
+    IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
+    IN PVOID Context
+);
+
+/* PSEH EXCEPTION HANDLING **************************************************/
+
+LONG
+NTAPI
+ExSystemExceptionFilter(VOID);
+
+/* CALLBACKS *****************************************************************/
+
+FORCEINLINE
+VOID
+ExDoCallBack(IN OUT PEX_CALLBACK Callback,
+             IN PVOID Context,
+             IN PVOID Argument1,
+             IN PVOID Argument2)
+{
+    PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
+    PEX_CALLBACK_FUNCTION Function;
+
+    /* Reference the block */
+    CallbackBlock = ExReferenceCallBackBlock(Callback);
+    if (CallbackBlock)
+    {
+        /* Get the function */
+        Function = ExGetCallBackBlockRoutine(CallbackBlock);
+
+        /* Do the callback */
+        Function(Context, Argument1, Argument2);
+
+        /* Now dereference it */
+        ExDereferenceCallBackBlock(Callback, CallbackBlock);
+    }
+}
+
+/* FAST REFS ******************************************************************/
+
+FORCEINLINE
+PVOID
+ExGetObjectFastReference(IN EX_FAST_REF FastRef)
+{
+    /* Return the unbiased pointer */
+    return (PVOID)(FastRef.Value & ~MAX_FAST_REFS);
+}
+
+FORCEINLINE
+ULONG
+ExGetCountFastReference(IN EX_FAST_REF FastRef)
+{
+    /* Return the reference count */
+    return FastRef.RefCnt;
+}
+
+FORCEINLINE
+VOID
+ExInitializeFastReference(OUT PEX_FAST_REF FastRef,
+                          IN OPTIONAL PVOID Object)
+{
+    /* Sanity check */
+    ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
+    
+    /* Check if an object is being set */
+    if (!Object)
+    {
+        /* Clear the field */
+        FastRef->Object = NULL;
+    }
+    else
+    {
+        /* Otherwise, we assume the object was referenced and is ready */
+        FastRef->Value = (ULONG_PTR)Object | MAX_FAST_REFS;
+    }
+}
+
+FORCEINLINE
+EX_FAST_REF
+ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef)
+{
+    EX_FAST_REF OldValue, NewValue;
+    
+    /* Start reference loop */
+    for (;;)
+    {
+        /* Get the current reference count */
+        OldValue = *FastRef;
+        if (OldValue.RefCnt)
+        {
+            /* Increase the reference count */
+            NewValue.Value = OldValue.Value - 1;
+            NewValue.Object = ExpChangePushlock(&FastRef->Object,
+                                                NewValue.Object,
+                                                OldValue.Object);
+            if (NewValue.Object != OldValue.Object) continue;
+        }
+        
+        /* We are done */
+        break;
+    }
+    
+    /* Return the old value */
+    return OldValue;
+}
+
+FORCEINLINE
+BOOLEAN
+ExInsertFastReference(IN OUT PEX_FAST_REF FastRef,
+                      IN PVOID Object)
+{
+    EX_FAST_REF OldValue, NewValue;
+    
+    /* Sanity checks */
+    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+    
+    /* Start update loop */
+    for (;;)
+    {
+        /* Get the current reference count */
+        OldValue = *FastRef;
+        
+        /* Check if the current count is too high or if the pointer changed */
+        if (((OldValue.RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
+            ((OldValue.Value &~ MAX_FAST_REFS) != (ULONG_PTR)Object))
+        {
+            /* Fail */
+            return FALSE;
+        }
+        
+        /* Update the reference count */
+        NewValue.Value = OldValue.Value + MAX_FAST_REFS;
+        NewValue.Object = ExpChangePushlock(&FastRef->Object,
+                                            NewValue.Object,
+                                            OldValue.Object);
+        if (NewValue.Object != OldValue.Object) continue;
+        
+        /* We are done */
+        break;
+    }
+    
+    /* Return success */
+    return TRUE;   
+}
+
+BOOLEAN
+FORCEINLINE
+ExReleaseFastReference(IN PEX_FAST_REF FastRef,
+                       IN PVOID Object)
+{
+    EX_FAST_REF OldValue, NewValue;
+    
+    /* Sanity checks */
+    ASSERT(Object != NULL);
+    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+    
+    /* Start reference loop */
+    for (;;)
+    {
+        /* Get the current reference count */
+        OldValue = *FastRef;
+        
+        /* Check if we're full if if the pointer changed */
+        if ((OldValue.Value ^ (ULONG_PTR)Object) >= MAX_FAST_REFS) return FALSE;
+            
+        /* Decrease the reference count */
+        NewValue.Value = OldValue.Value + 1;
+        NewValue.Object = ExpChangePushlock(&FastRef->Object,
+                                            NewValue.Object,
+                                            OldValue.Object);
+        if (NewValue.Object != OldValue.Object) continue;
+        
+        /* We are done */
+        break;
+    }
+    
+    /* Return success */
+    return TRUE;
+}
+
+EX_FAST_REF
+FORCEINLINE
+ExSwapFastReference(IN PEX_FAST_REF FastRef,
+                    IN PVOID Object)
+{
+    EX_FAST_REF NewValue, OldValue;
+    
+    /* Sanity check */
+    ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
+    
+    /* Check if an object is being set */
+    if (!Object)
+    {
+        /* Clear the field */
+        NewValue.Object = NULL;
+    }
+    else
+    {
+        /* Otherwise, we assume the object was referenced and is ready */
+        NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS;
+    }
+    
+    /* Update the object */
+    OldValue.Object = InterlockedExchangePointer(&FastRef->Object, NewValue.Object);
+    return OldValue;
+}
+
+EX_FAST_REF
+FORCEINLINE
+ExCompareSwapFastReference(IN PEX_FAST_REF FastRef,
+                           IN PVOID Object,
+                           IN PVOID OldObject)
+{
+    EX_FAST_REF OldValue, NewValue;
+    
+    /* Sanity check and start swap loop */
+    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
+    for (;;)
+    {
+        /* Get the current value */
+        OldValue = *FastRef;
+        
+        /* Make sure there's enough references to swap */
+        if (!((OldValue.Value ^ (ULONG_PTR)OldObject) <= MAX_FAST_REFS)) break;
+        
+        /* Check if we have an object to swap */
+        if (Object)
+        {
+            /* Set up the value with maximum fast references */
+            NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS;
+        }
+        else
+        {
+            /* Write the object address itself (which is empty) */
+            NewValue.Value = (ULONG_PTR)Object;
+        }
+        
+        /* Do the actual compare exchange */
+        NewValue.Object = ExpChangePushlock(&FastRef->Object,
+                                            NewValue.Object,
+                                            OldValue.Object);
+        if (NewValue.Object != OldValue.Object) continue;
+        
+        /* All done */
+        break;
+    }
+    
+    /* Return the old value */
+    return OldValue;
+}
+
+/* RUNDOWN *******************************************************************/
 
 /*++
  * @name ExfAcquireRundownProtection

Modified: trunk/reactos/ntoskrnl/ob/obref.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obref.c?rev=39859&r1=39858&r2=39859&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obref.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ob/obref.c [iso-8859-1] Tue Mar  3 23:24:10 2009
@@ -109,21 +109,9 @@
 {
     /* Check if we were given an object and reference it 7 times */
     if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
-
-    /* Sanity check */
-    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
-
-    /* Check if the caller gave us an object */
-    if (Object)
-    {
-        /* He did, so write the biased pointer */
-        FastRef->Object = (PVOID)((ULONG_PTR)Object | MAX_FAST_REFS);
-    }
-    else
-    {
-        /* Otherwise, clear the current object */
-        FastRef->Object = NULL;
-    }
+    
+    /* Setup the fast reference */
+    ExInitializeFastReference(FastRef, Object);
 }
 
 PVOID
@@ -131,9 +119,10 @@
 ObFastReferenceObjectLocked(IN PEX_FAST_REF FastRef)
 {
     PVOID Object;
+    EX_FAST_REF OldValue = *FastRef;
 
     /* Get the object and reference it slowly */
-    Object = (PVOID)((ULONG_PTR)FastRef->Object & MAX_FAST_REFS);
+    Object = ExGetObjectFastReference(OldValue);
     if (Object) ObReferenceObject(Object);
     return Object;
 }
@@ -142,25 +131,16 @@
 FASTCALL
 ObFastReferenceObject(IN PEX_FAST_REF FastRef)
 {
-    ULONG_PTR Value, NewValue;
+    EX_FAST_REF OldValue;
     ULONG_PTR Count;
     PVOID Object;
 
-    /* Start reference loop */
-    for (;;)
-    {
-        /* Get the current count */
-        Value = FastRef->Value;
-        if (!(Value & MAX_FAST_REFS)) break;
-
-        /* Increase the reference count */
-        NewValue = Value - 1;
-        if (ExpChangeRundown(FastRef, NewValue, Value) == Value) break;
-    }
-
-    /* Get the object and count */
-    Object = (PVOID)(Value &~ MAX_FAST_REFS);
-    Count = Value & MAX_FAST_REFS;
+    /* Reference the object and get it pointer */
+    OldValue = ExAcquireFastReference(FastRef);
+    Object = ExGetObjectFastReference(OldValue);
+
+    /* Check how many references are left */
+    Count = ExGetCountFastReference(OldValue);
 
     /* Check if the reference count is over 1 */
     if (Count > 1) return Object;
@@ -170,25 +150,12 @@
 
     /* Otherwise, reference the object 7 times */
     ObReferenceObjectEx(Object, MAX_FAST_REFS);
-    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
-
-    for (;;)
-    {
-        /* Check if the current count is too high */
-        Value = FastRef->Value;
-        if (((FastRef->RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
-            ((PVOID)((ULONG_PTR)FastRef->Object &~ MAX_FAST_REFS) != Object))
-        {
-            /* Completely dereference the object */
-            ObDereferenceObjectEx(Object, MAX_FAST_REFS);
-            break;
-        }
-        else
-        {
-            /* Increase the reference count */
-            NewValue = Value + MAX_FAST_REFS;
-            if (ExpChangeRundown(FastRef, NewValue, Value) == Value) break;
-        }
+    
+    /* Now update the reference count */
+    if (!ExInsertFastReference(FastRef, Object))
+    {
+        /* We failed: completely dereference the object */
+        ObDereferenceObjectEx(Object, MAX_FAST_REFS);
     }
 
     /* Return the Object */
@@ -200,30 +167,8 @@
 ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
                         IN PVOID Object)
 {
-    ULONG_PTR Value, NewValue;
-
-    /* Sanity checks */
-    ASSERT(Object);
-    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
-
-    /* Start dereference loop */
-    for (;;)
-    {
-        /* Get the current count */
-        Value = FastRef->Value;
-        if ((Value ^ (ULONG_PTR)Object) < MAX_FAST_REFS)
-        {
-            /* Decrease the reference count */
-            NewValue = Value + 1;
-            if (ExpChangeRundown(FastRef, NewValue, Value) == Value) return;
-        }
-        else
-        {
-            /* Do a normal Dereference */
-            ObDereferenceObject(Object);
-            return;
-        }
-    }
+    /* Release a fast reference. If this failed, use the slow path */
+    if (!ExReleaseFastReference(FastRef, Object)) ObDereferenceObject(Object);
 }
 
 PVOID
@@ -231,36 +176,20 @@
 ObFastReplaceObject(IN PEX_FAST_REF FastRef,
                     PVOID Object)
 {
-    ULONG_PTR NewValue;
-    EX_FAST_REF OldRef;
+    EX_FAST_REF OldValue;
     PVOID OldObject;
+    ULONG_PTR Count;
 
     /* Check if we were given an object and reference it 7 times */
     if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
-
-    /* Sanity check */
-    ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
-
-    /* Check if the caller gave us an object */
-    if (Object)
-    {
-        /* He did, so bias the pointer */
-        NewValue = (ULONG_PTR)Object | MAX_FAST_REFS;
-    }
-    else
-    {
-        /* No object, we're clearing */
-        NewValue = 0;
-    }
-
-    /* Switch objects */
-    OldRef.Value = InterlockedExchange((PLONG)&FastRef->Value, NewValue);
-    OldObject = (PVOID)((ULONG_PTR)OldRef.Object &~ MAX_FAST_REFS);
-    if ((OldObject) && (OldRef.RefCnt))
-    {
-        /* Dereference the old object */
-        ObDereferenceObjectEx(OldObject, OldRef.RefCnt);
-    }
+    
+    /* Do the swap */
+    OldValue = ExSwapFastReference(FastRef, Object);
+    OldObject = ExGetObjectFastReference(OldValue);
+    
+    /* Check if we had an active object and dereference it */
+    Count = ExGetCountFastReference(OldValue);
+    if ((OldObject) && (Count)) ObDereferenceObjectEx(OldObject, Count);
 
     /* Return the old object */
     return OldObject;



More information about the Ros-diffs mailing list