Skip to content

Commit d285291

Browse files
committed
sync.h: Imply negative assertions when calling LOCK
1 parent bba87c0 commit d285291

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

src/sync.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,26 @@ class SCOPED_LOCKABLE UniqueLock : public Base
244244
template<typename MutexArg>
245245
using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
246246

247-
#define LOCK(cs) DebugLock<decltype(cs)> UNIQUE_NAME(criticalblock)(cs, #cs, __FILE__, __LINE__)
247+
// When locking a Mutex, require negative capability to ensure the lock
248+
// is not already held
249+
inline Mutex& MaybeCheckNotHeld(Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
250+
inline Mutex* MaybeCheckNotHeld(Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
251+
252+
// When locking a GlobalMutex, just check it is not locked in the surrounding scope
253+
inline GlobalMutex& MaybeCheckNotHeld(GlobalMutex& cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
254+
inline GlobalMutex* MaybeCheckNotHeld(GlobalMutex* cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
255+
256+
// When locking a RecursiveMutex, it's okay to already hold the lock
257+
// but check that it is not known to be locked in the surrounding scope anyway
258+
inline RecursiveMutex& MaybeCheckNotHeld(RecursiveMutex& cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
259+
inline RecursiveMutex* MaybeCheckNotHeld(RecursiveMutex* cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
260+
261+
#define LOCK(cs) DebugLock<decltype(cs)> UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
248262
#define LOCK2(cs1, cs2) \
249-
DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \
250-
DebugLock<decltype(cs2)> criticalblock2(cs2, #cs2, __FILE__, __LINE__);
251-
#define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__, true)
252-
#define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__)
263+
DebugLock<decltype(cs1)> criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
264+
DebugLock<decltype(cs2)> criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__);
265+
#define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true)
266+
#define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
253267

254268
#define ENTER_CRITICAL_SECTION(cs) \
255269
{ \
@@ -288,7 +302,7 @@ using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove
288302
//!
289303
//! The above is detectable at compile-time with the -Wreturn-local-addr flag in
290304
//! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
291-
#define WITH_LOCK(cs, code) [&]() -> decltype(auto) { LOCK(cs); code; }()
305+
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
292306

293307
class CSemaphore
294308
{

0 commit comments

Comments
 (0)