summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/Lock.cpp9
-rw-r--r--Kernel/Thread.cpp4
-rw-r--r--Kernel/Thread.h3
-rw-r--r--Kernel/WaitQueue.cpp4
-rw-r--r--Kernel/WaitQueue.h3
5 files changed, 13 insertions, 10 deletions
diff --git a/Kernel/Lock.cpp b/Kernel/Lock.cpp
index f1d0888dee..a9d7929495 100644
--- a/Kernel/Lock.cpp
+++ b/Kernel/Lock.cpp
@@ -18,8 +18,7 @@ void Lock::lock()
m_lock.store(false, AK::memory_order_release);
return;
}
- m_lock.store(false, AK::memory_order_release);
- current->wait_on(m_queue, m_holder, m_name);
+ current->wait_on(m_queue, &m_lock, m_holder, m_name);
}
}
}
@@ -37,8 +36,7 @@ void Lock::unlock()
return;
}
m_holder = nullptr;
- m_queue.wake_one();
- m_lock.store(false, AK::memory_order_release);
+ m_queue.wake_one(&m_lock);
return;
}
// I don't know *who* is using "m_lock", so just yield.
@@ -66,8 +64,7 @@ bool Lock::unlock_if_locked()
return false;
}
m_holder = nullptr;
- m_lock.store(false, AK::memory_order_release);
- m_queue.wake_one();
+ m_queue.wake_one(&m_lock);
return true;
}
// I don't know *who* is using "m_lock", so just yield.
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index 31e15d17b9..7e63c88ef9 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -783,10 +783,12 @@ const LogStream& operator<<(const LogStream& stream, const Thread& value)
return stream << value.process().name() << "(" << value.pid() << ":" << value.tid() << ")";
}
-void Thread::wait_on(WaitQueue& queue, Thread* beneficiary, const char* reason)
+void Thread::wait_on(WaitQueue& queue, Atomic<bool>* lock, Thread* beneficiary, const char* reason)
{
bool did_unlock = unlock_process_if_locked();
cli();
+ if (lock)
+ *lock = false;
set_state(State::Queued);
queue.enqueue(*current);
// Yield and wait for the queue to wake us up again.
diff --git a/Kernel/Thread.h b/Kernel/Thread.h
index c17b43bbba..18f8546464 100644
--- a/Kernel/Thread.h
+++ b/Kernel/Thread.h
@@ -1,5 +1,6 @@
#pragma once
+#include <AK/Atomic.h>
#include <AK/Function.h>
#include <AK/IntrusiveList.h>
#include <AK/OwnPtr.h>
@@ -300,7 +301,7 @@ public:
return block<ConditionBlocker>(state_string, move(condition));
}
- void wait_on(WaitQueue& queue, Thread* beneficiary = nullptr, const char* reason = nullptr);
+ void wait_on(WaitQueue& queue, Atomic<bool>* lock = nullptr, Thread* beneficiary = nullptr, const char* reason = nullptr);
void wake_from_queue();
void unblock();
diff --git a/Kernel/WaitQueue.cpp b/Kernel/WaitQueue.cpp
index e3541e93f3..9ea2f9f50c 100644
--- a/Kernel/WaitQueue.cpp
+++ b/Kernel/WaitQueue.cpp
@@ -15,9 +15,11 @@ void WaitQueue::enqueue(Thread& thread)
m_threads.append(thread);
}
-void WaitQueue::wake_one()
+void WaitQueue::wake_one(Atomic<bool>* lock)
{
InterruptDisabler disabler;
+ if (lock)
+ *lock = false;
if (m_threads.is_empty())
return;
if (auto* thread = m_threads.take_first())
diff --git a/Kernel/WaitQueue.h b/Kernel/WaitQueue.h
index ebe46702bf..81893af25a 100644
--- a/Kernel/WaitQueue.h
+++ b/Kernel/WaitQueue.h
@@ -1,5 +1,6 @@
#pragma once
+#include <AK/Atomic.h>
#include <AK/SinglyLinkedList.h>
#include <Kernel/Thread.h>
@@ -9,7 +10,7 @@ public:
~WaitQueue();
void enqueue(Thread&);
- void wake_one();
+ void wake_one(Atomic<bool>* lock = nullptr);
void wake_all();
private: