Author: gedmurphy Date: Fri May 19 09:15:35 2017 New Revision: 74588 URL: http://svn.reactos.org/svn/reactos?rev=74588&view=rev Log: [FLTMGR} - Implement FltAcquirePushLockExclusive, FltAcquirePushLockShared and FltReleasePushLock. Lifted from ntos' internal pushlock routines. - Implement FltpObjectPointerReference and partially implement FltpObjectPointerDerference
Modified: trunk/reactos/drivers/filters/fltmgr/Object.c Modified: trunk/reactos/drivers/filters/fltmgr/Object.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filters/fltmgr/Object.c?rev=74588&r1=74587&r2=74588&view=diff ============================================================================== --- trunk/reactos/drivers/filters/fltmgr/Object.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filters/fltmgr/Object.c [iso-8859-1] Fri May 19 09:15:35 2017 @@ -20,7 +20,18 @@ /* DATA *********************************************************************/ - +#define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z) + +// +// Pushlock bits +// +#define EX_PUSH_LOCK_LOCK_V ((ULONG_PTR)0x0) +#define EX_PUSH_LOCK_LOCK ((ULONG_PTR)0x1) +#define EX_PUSH_LOCK_WAITING ((ULONG_PTR)0x2) +#define EX_PUSH_LOCK_WAKING ((ULONG_PTR)0x4) +#define EX_PUSH_LOCK_MULTIPLE_SHARED ((ULONG_PTR)0x8) +#define EX_PUSH_LOCK_SHARE_INC ((ULONG_PTR)0x10) +#define EX_PUSH_LOCK_PTR_BITS ((ULONG_PTR)0xf) /* EXPORTED FUNCTIONS ******************************************************/ @@ -42,6 +53,85 @@ FltObjectDereference(_Inout_ PVOID Object) { FltpExReleaseRundownProtection(&((PFLT_OBJECT)Object)->RundownRef); +} + + +_Acquires_lock_(_Global_critical_region_) +_IRQL_requires_max_(APC_LEVEL) +VOID +FLTAPI +FltAcquirePushLockExclusive(_Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) PEX_PUSH_LOCK PushLock) +{ + KeEnterCriticalRegion(); + + /* Try acquiring the lock */ + if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V)) + { + /* Someone changed it, use the slow path */ + ExfAcquirePushLockExclusive(PushLock); + } + + /* Sanity check */ + FLT_ASSERT(PushLock->Locked); +} + + +_Acquires_lock_(_Global_critical_region_) +_IRQL_requires_max_(APC_LEVEL) +VOID +FLTAPI +FltAcquirePushLockShared(_Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) PEX_PUSH_LOCK PushLock) +{ + EX_PUSH_LOCK NewValue; + + KeEnterCriticalRegion(); + + /* Try acquiring the lock */ + NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC; + if (ExpChangePushlock(PushLock, NewValue.Ptr, 0)) + { + /* Someone changed it, use the slow path */ + ExfAcquirePushLockShared(PushLock); + } + + /* Sanity checks */ + ASSERT(PushLock->Locked); +} + +_Releases_lock_(_Global_critical_region_) +_IRQL_requires_max_(APC_LEVEL) +VOID +FLTAPI +FltReleasePushLock(_Inout_ _Requires_lock_held_(*_Curr_) _Releases_lock_(*_Curr_) PEX_PUSH_LOCK PushLock) +{ + EX_PUSH_LOCK OldValue = *PushLock; + EX_PUSH_LOCK NewValue; + + /* Sanity checks */ + FLT_ASSERT(OldValue.Locked); + + /* Check if the pushlock is shared */ + if (OldValue.Shared > 1) + { + /* Decrease the share count */ + NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC; + } + else + { + /* Clear the pushlock entirely */ + NewValue.Value = 0; + } + + /* Check if nobody is waiting on us and try clearing the lock here */ + if ((OldValue.Waiting) || + (ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) != + OldValue.Ptr)) + { + /* We have waiters, use the long path */ + ExfReleasePushLock(PushLock); + } + + KeLeaveCriticalRegion(); } @@ -157,3 +247,26 @@ return Status; } + +ULONG +FltpObjectPointerReference(_In_ PFLT_OBJECT Object) +{ + PULONG Result; + + /* Store the old count and increment */ + Result = &Object->PointerCount; + InterlockedIncrement((PLONG)&Object->PointerCount); + + /* Return the initial value */ + return *Result; +} + +VOID +FltpObjectPointerDereference(_In_ PFLT_OBJECT Object) +{ + if (!InterlockedDecrement((PLONG)Object->PointerCount)) + { + // Cleanup + FLT_ASSERT(FALSE); + } +}