From d2852917eecad6ab422a7b2c9892d351a7f0cc96 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 20 Apr 2022 17:11:07 +1000 Subject: [PATCH] sync.h: Imply negative assertions when calling LOCK --- src/sync.h | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/sync.h b/src/sync.h index b094b5d2e2..7ec4b668ac 100644 --- a/src/sync.h +++ b/src/sync.h @@ -244,12 +244,26 @@ public: template using DebugLock = UniqueLock::type>::type>; -#define LOCK(cs) DebugLock UNIQUE_NAME(criticalblock)(cs, #cs, __FILE__, __LINE__) +// When locking a Mutex, require negative capability to ensure the lock +// is not already held +inline Mutex& MaybeCheckNotHeld(Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; } +inline Mutex* MaybeCheckNotHeld(Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; } + +// When locking a GlobalMutex, just check it is not locked in the surrounding scope +inline GlobalMutex& MaybeCheckNotHeld(GlobalMutex& cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; } +inline GlobalMutex* MaybeCheckNotHeld(GlobalMutex* cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; } + +// When locking a RecursiveMutex, it's okay to already hold the lock +// but check that it is not known to be locked in the surrounding scope anyway +inline RecursiveMutex& MaybeCheckNotHeld(RecursiveMutex& cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; } +inline RecursiveMutex* MaybeCheckNotHeld(RecursiveMutex* cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; } + +#define LOCK(cs) DebugLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) #define LOCK2(cs1, cs2) \ - DebugLock criticalblock1(cs1, #cs1, __FILE__, __LINE__); \ - DebugLock criticalblock2(cs2, #cs2, __FILE__, __LINE__); -#define TRY_LOCK(cs, name) DebugLock name(cs, #cs, __FILE__, __LINE__, true) -#define WAIT_LOCK(cs, name) DebugLock name(cs, #cs, __FILE__, __LINE__) + DebugLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \ + DebugLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__); +#define TRY_LOCK(cs, name) DebugLock name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true) +#define WAIT_LOCK(cs, name) DebugLock name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) #define ENTER_CRITICAL_SECTION(cs) \ { \ @@ -288,7 +302,7 @@ using DebugLock = UniqueLock decltype(auto) { LOCK(cs); code; }() +#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }()) class CSemaphore {