mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 19:17:41 +00:00
Kernel: Protect Mutex's thread lists with a spinlock
This commit is contained in:
parent
8296dd9955
commit
b28beb691e
2 changed files with 53 additions and 43 deletions
|
@ -206,16 +206,21 @@ void Mutex::block(Thread& current_thread, Mode mode, SpinlockLocker<Spinlock>& l
|
||||||
{
|
{
|
||||||
if constexpr (LOCK_IN_CRITICAL_DEBUG)
|
if constexpr (LOCK_IN_CRITICAL_DEBUG)
|
||||||
VERIFY_INTERRUPTS_ENABLED();
|
VERIFY_INTERRUPTS_ENABLED();
|
||||||
auto& blocked_thread_list = thread_list_for_mode(mode);
|
m_blocked_thread_lists.with([&](auto& lists) {
|
||||||
VERIFY(!blocked_thread_list.contains(current_thread));
|
auto& list = lists.list_for_mode(mode);
|
||||||
blocked_thread_list.append(current_thread);
|
VERIFY(!list.contains(current_thread));
|
||||||
|
list.append(current_thread);
|
||||||
|
});
|
||||||
|
|
||||||
dbgln_if(LOCK_TRACE_DEBUG, "Mutex::lock @ {} ({}) waiting...", this, m_name);
|
dbgln_if(LOCK_TRACE_DEBUG, "Mutex::lock @ {} ({}) waiting...", this, m_name);
|
||||||
current_thread.block(*this, lock, requested_locks);
|
current_thread.block(*this, lock, requested_locks);
|
||||||
dbgln_if(LOCK_TRACE_DEBUG, "Mutex::lock @ {} ({}) waited", this, m_name);
|
dbgln_if(LOCK_TRACE_DEBUG, "Mutex::lock @ {} ({}) waited", this, m_name);
|
||||||
|
|
||||||
VERIFY(blocked_thread_list.contains(current_thread));
|
m_blocked_thread_lists.with([&](auto& lists) {
|
||||||
blocked_thread_list.remove(current_thread);
|
auto& list = lists.list_for_mode(mode);
|
||||||
|
VERIFY(list.contains(current_thread));
|
||||||
|
list.remove(current_thread);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mutex::unblock_waiters(Mode previous_mode)
|
void Mutex::unblock_waiters(Mode previous_mode)
|
||||||
|
@ -223,41 +228,43 @@ void Mutex::unblock_waiters(Mode previous_mode)
|
||||||
VERIFY(m_times_locked == 0);
|
VERIFY(m_times_locked == 0);
|
||||||
VERIFY(m_mode == Mode::Unlocked);
|
VERIFY(m_mode == Mode::Unlocked);
|
||||||
|
|
||||||
if (m_blocked_threads_list_exclusive.is_empty() && m_blocked_threads_list_shared.is_empty())
|
m_blocked_thread_lists.with([&](auto& lists) {
|
||||||
return;
|
if (lists.exclusive.is_empty() && lists.shared.is_empty())
|
||||||
|
return;
|
||||||
|
|
||||||
auto unblock_shared = [&]() {
|
auto unblock_shared = [&]() {
|
||||||
if (m_blocked_threads_list_shared.is_empty())
|
if (lists.shared.is_empty())
|
||||||
return false;
|
return false;
|
||||||
m_mode = Mode::Shared;
|
m_mode = Mode::Shared;
|
||||||
for (auto& thread : m_blocked_threads_list_shared) {
|
for (auto& thread : lists.shared) {
|
||||||
auto requested_locks = thread.unblock_from_mutex(*this);
|
auto requested_locks = thread.unblock_from_mutex(*this);
|
||||||
m_shared_holders += requested_locks;
|
m_shared_holders += requested_locks;
|
||||||
#if LOCK_SHARED_UPGRADE_DEBUG
|
#if LOCK_SHARED_UPGRADE_DEBUG
|
||||||
auto set_result = m_shared_holders_map.set(&thread, requested_locks);
|
auto set_result = m_shared_holders_map.set(&thread, requested_locks);
|
||||||
VERIFY(set_result == AK::HashSetResult::InsertedNewEntry);
|
VERIFY(set_result == AK::HashSetResult::InsertedNewEntry);
|
||||||
#endif
|
#endif
|
||||||
m_times_locked += requested_locks;
|
m_times_locked += requested_locks;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
};
|
|
||||||
auto unblock_exclusive = [&]() {
|
|
||||||
if (auto* next_exclusive_thread = m_blocked_threads_list_exclusive.first()) {
|
|
||||||
m_mode = Mode::Exclusive;
|
|
||||||
m_times_locked = next_exclusive_thread->unblock_from_mutex(*this);
|
|
||||||
m_holder = next_exclusive_thread;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
return false;
|
auto unblock_exclusive = [&]() {
|
||||||
};
|
if (auto* next_exclusive_thread = lists.exclusive.first()) {
|
||||||
|
m_mode = Mode::Exclusive;
|
||||||
|
m_times_locked = next_exclusive_thread->unblock_from_mutex(*this);
|
||||||
|
m_holder = next_exclusive_thread;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
if (previous_mode == Mode::Exclusive) {
|
if (previous_mode == Mode::Exclusive) {
|
||||||
if (!unblock_shared())
|
if (!unblock_shared())
|
||||||
unblock_exclusive();
|
unblock_exclusive();
|
||||||
} else {
|
} else {
|
||||||
if (!unblock_exclusive())
|
if (!unblock_exclusive())
|
||||||
unblock_shared();
|
unblock_shared();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Mutex::force_unlock_exclusive_if_locked(u32& lock_count_to_restore) -> Mode
|
auto Mutex::force_unlock_exclusive_if_locked(u32& lock_count_to_restore) -> Mode
|
||||||
|
|
|
@ -72,12 +72,6 @@ public:
|
||||||
private:
|
private:
|
||||||
using BlockedThreadList = IntrusiveList<&Thread::m_blocked_threads_list_node>;
|
using BlockedThreadList = IntrusiveList<&Thread::m_blocked_threads_list_node>;
|
||||||
|
|
||||||
ALWAYS_INLINE BlockedThreadList& thread_list_for_mode(Mode mode)
|
|
||||||
{
|
|
||||||
VERIFY(mode == Mode::Exclusive || mode == Mode::Shared);
|
|
||||||
return mode == Mode::Exclusive ? m_blocked_threads_list_exclusive : m_blocked_threads_list_shared;
|
|
||||||
}
|
|
||||||
|
|
||||||
void block(Thread&, Mode, SpinlockLocker<Spinlock>&, u32);
|
void block(Thread&, Mode, SpinlockLocker<Spinlock>&, u32);
|
||||||
void unblock_waiters(Mode);
|
void unblock_waiters(Mode);
|
||||||
|
|
||||||
|
@ -96,8 +90,17 @@ private:
|
||||||
RefPtr<Thread> m_holder;
|
RefPtr<Thread> m_holder;
|
||||||
size_t m_shared_holders { 0 };
|
size_t m_shared_holders { 0 };
|
||||||
|
|
||||||
BlockedThreadList m_blocked_threads_list_exclusive;
|
struct BlockedThreadLists {
|
||||||
BlockedThreadList m_blocked_threads_list_shared;
|
BlockedThreadList exclusive;
|
||||||
|
BlockedThreadList shared;
|
||||||
|
|
||||||
|
ALWAYS_INLINE BlockedThreadList& list_for_mode(Mode mode)
|
||||||
|
{
|
||||||
|
VERIFY(mode == Mode::Exclusive || mode == Mode::Shared);
|
||||||
|
return mode == Mode::Exclusive ? exclusive : shared;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SpinlockProtected<BlockedThreadLists> m_blocked_thread_lists;
|
||||||
|
|
||||||
mutable Spinlock m_lock;
|
mutable Spinlock m_lock;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue