summaryrefslogtreecommitdiff
path: root/Libraries/LibThread/Lock.h
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-13 12:29:41 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-13 12:33:42 +0200
commit94647fa4abebd187e1abd7f0d01681dd9d08ea9b (patch)
tree267b002579c4e90386baaa4230371cd06c2d6ea9 /Libraries/LibThread/Lock.h
parent02e0fab19af9cf892ee651e5916c9895703cefdd (diff)
downloadserenity-94647fa4abebd187e1abd7f0d01681dd9d08ea9b.zip
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.
Diffstat (limited to 'Libraries/LibThread/Lock.h')
-rw-r--r--Libraries/LibThread/Lock.h42
1 files changed, 15 insertions, 27 deletions
diff --git a/Libraries/LibThread/Lock.h b/Libraries/LibThread/Lock.h
index 2ae3def054..dd3b6e55f1 100644
--- a/Libraries/LibThread/Lock.h
+++ b/Libraries/LibThread/Lock.h
@@ -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)