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