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/…
==============================================================================
--- 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=39…
==============================================================================
--- 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;