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=... ============================================================================== --- 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/e... ============================================================================== --- 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=398... ============================================================================== --- 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;