1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 18:47:44 +00:00

LibThread: Simplify the userspace Lock to remove CAS on unlock()

Instead of using a separate synchronization variable, just use the lock
holder TID for synchronization. This way, we only need to CAS when
first acquiring a lock.
This commit is contained in:
Andreas Kling 2020-04-13 12:29:41 +02:00
parent 02e0fab19a
commit 94647fa4ab

View file

@ -44,9 +44,8 @@ public:
void unlock(); void unlock();
private: private:
AK::Atomic<bool> m_lock { false }; Atomic<int> m_holder { 0 };
u32 m_level { 0 }; u32 m_level { 0 };
int m_holder { -1 };
}; };
class Locker { class Locker {
@ -67,16 +66,16 @@ private:
[[gnu::always_inline]] inline void Lock::lock() [[gnu::always_inline]] inline void Lock::lock()
{ {
int tid = gettid(); int tid = gettid();
if (m_holder == tid) {
++m_level;
return;
}
for (;;) { for (;;) {
bool expected = false; int expected = 0;
if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) { if (m_holder.compare_exchange_strong(expected, tid, AK::memory_order_acq_rel)) {
if (m_holder == -1 || m_holder == tid) { m_holder = tid;
m_holder = tid; m_level = 1;
++m_level; return;
m_lock.store(false, AK::memory_order_release);
return;
}
m_lock.store(false, AK::memory_order_release);
} }
donate(m_holder); donate(m_holder);
} }
@ -84,22 +83,11 @@ private:
inline void Lock::unlock() inline void Lock::unlock()
{ {
for (;;) { ASSERT(m_holder == gettid());
bool expected = false; ASSERT(m_level);
if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) { --m_level;
ASSERT(m_holder == gettid()); if (!m_level)
ASSERT(m_level); m_holder.store(0, AK::memory_order_release);
--m_level;
if (m_level) {
m_lock.store(false, AK::memory_order_release);
return;
}
m_holder = -1;
m_lock.store(false, AK::memory_order_release);
return;
}
donate(m_holder);
}
} }
#define LOCKER(lock) LibThread::Locker locker(lock) #define LOCKER(lock) LibThread::Locker locker(lock)