From bb1fa019de43de8a03e5c0c9ed79fc043ae5163f Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Mon, 19 Jul 2021 10:32:55 -0700 Subject: [PATCH] Kernel: Allow MutexLocker to be conditionally initialized There are cases where we want to conditionally take a lock, but still would like to use an RAII type to make sure we don't leak the lock. This was previously impossible to do with `MutexLocker` due to it's design. This commit tweaks the design to allow the object to be initialized to an "empty" state without a lock associated, so it does nothing, and then later a lock can be "attached" to the locker. I realized that the get_lock() API's where also unused, and would no longer make sense for empty locks, so they were removed. --- Kernel/Mutex.h | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/Kernel/Mutex.h b/Kernel/Mutex.h index 4bb30b6264..28373416c0 100644 --- a/Kernel/Mutex.h +++ b/Kernel/Mutex.h @@ -106,18 +106,26 @@ private: }; class MutexLocker { + AK_MAKE_NONCOPYABLE(MutexLocker); + public: + ALWAYS_INLINE explicit MutexLocker() + : m_lock(nullptr) + , m_locked(false) + { + } + #if LOCK_DEBUG ALWAYS_INLINE explicit MutexLocker(Mutex& l, Mutex::Mode mode = Mutex::Mode::Exclusive, const SourceLocation& location = SourceLocation::current()) #else ALWAYS_INLINE explicit MutexLocker(Mutex& l, Mutex::Mode mode = Mutex::Mode::Exclusive) #endif - : m_lock(l) + : m_lock(&l) { #if LOCK_DEBUG - m_lock.lock(mode, location); + m_lock->lock(mode, location); #else - m_lock.lock(mode); + m_lock->lock(mode); #endif } @@ -126,11 +134,30 @@ public: if (m_locked) unlock(); } + ALWAYS_INLINE void unlock() { + VERIFY(m_lock); VERIFY(m_locked); m_locked = false; - m_lock.unlock(); + m_lock->unlock(); + } + +#if LOCK_DEBUG + ALWAYS_INLINE void attach_and_lock(Mutex& lock, Mutex::Mode mode = Mutex::Mode::Exclusive, const SourceLocation& location = SourceLocation::current()) +#else + ALWAYS_INLINE void attach_and_lock(Mutex& lock, Mutex::Mode mode = Mutex::Mode::Exclusive) +#endif + { + VERIFY(!m_locked); + m_lock = &lock; + m_locked = true; + +#if LOCK_DEBUG + m_lock->lock(mode, location); +#else + m_lock->lock(mode); +#endif } #if LOCK_DEBUG @@ -139,21 +166,19 @@ public: ALWAYS_INLINE void lock(Mutex::Mode mode = Mutex::Mode::Exclusive) #endif { + VERIFY(m_lock); VERIFY(!m_locked); m_locked = true; #if LOCK_DEBUG - m_lock.lock(mode, location); + m_lock->lock(mode, location); #else - m_lock.lock(mode); + m_lock->lock(mode); #endif } - Mutex& get_lock() { return m_lock; } - const Mutex& get_lock() const { return m_lock; } - private: - Mutex& m_lock; + Mutex* m_lock; bool m_locked { true }; };