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

Kernel: Use IntrusiveList to make WaitQueue allocation-free :^)

This commit is contained in:
Andreas Kling 2019-12-22 12:23:44 +01:00
parent 96cfddb3ac
commit f4978b2be1
4 changed files with 30 additions and 26 deletions

View file

@ -776,3 +776,25 @@ const char* to_string(ThreadPriority priority)
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
return nullptr; return nullptr;
} }
void Thread::wait_on(WaitQueue& queue, Thread* beneficiary, const char* reason)
{
bool did_unlock = unlock_process_if_locked();
cli();
set_state(State::Queued);
queue.enqueue(*current);
// Yield and wait for the queue to wake us up again.
if (beneficiary)
Scheduler::donate_to(beneficiary, reason);
else
Scheduler::yield();
// We've unblocked, relock the process if needed and carry on.
if (did_unlock)
relock_process();
}
void Thread::wake_from_queue()
{
ASSERT(state() == State::Queued);
set_state(State::Runnable);
}

View file

@ -11,7 +11,6 @@
#include <Kernel/Scheduler.h> #include <Kernel/Scheduler.h>
#include <Kernel/UnixTypes.h> #include <Kernel/UnixTypes.h>
#include <Kernel/VM/Region.h> #include <Kernel/VM/Region.h>
#include <Kernel/WaitQueue.h>
#include <LibC/fd_set.h> #include <LibC/fd_set.h>
class Alarm; class Alarm;
@ -291,27 +290,8 @@ public:
return block<ConditionBlocker>(state_string, move(condition)); return block<ConditionBlocker>(state_string, move(condition));
} }
void wait_on(WaitQueue& queue, Thread* beneficiary = nullptr, const char* reason = nullptr) void wait_on(WaitQueue& queue, Thread* beneficiary = nullptr, const char* reason = nullptr);
{ void wake_from_queue();
bool did_unlock = unlock_process_if_locked();
cli();
set_state(State::Queued);
queue.enqueue(*current);
// Yield and wait for the queue to wake us up again.
if (beneficiary)
Scheduler::donate_to(beneficiary, reason);
else
Scheduler::yield();
// We've unblocked, relock the process if needed and carry on.
if (did_unlock)
relock_process();
}
void wake_from_queue()
{
ASSERT(state() == State::Queued);
set_state(State::Runnable);
}
void unblock(); void unblock();
@ -423,9 +403,11 @@ public:
private: private:
IntrusiveListNode m_runnable_list_node; IntrusiveListNode m_runnable_list_node;
IntrusiveListNode m_wait_queue_node;
private: private:
friend class SchedulerData; friend class SchedulerData;
friend class WaitQueue;
bool unlock_process_if_locked(); bool unlock_process_if_locked();
void relock_process(); void relock_process();

View file

@ -12,7 +12,7 @@ WaitQueue::~WaitQueue()
void WaitQueue::enqueue(Thread& thread) void WaitQueue::enqueue(Thread& thread)
{ {
InterruptDisabler disabler; InterruptDisabler disabler;
m_threads.append(&thread); m_threads.append(thread);
} }
void WaitQueue::wake_one() void WaitQueue::wake_one()

View file

@ -1,8 +1,7 @@
#pragma once #pragma once
#include <AK/SinglyLinkedList.h> #include <AK/SinglyLinkedList.h>
#include <Kernel/Thread.h>
class Thread;
class WaitQueue { class WaitQueue {
public: public:
@ -14,5 +13,6 @@ public:
void wake_all(); void wake_all();
private: private:
SinglyLinkedList<Thread*> m_threads; typedef IntrusiveList<Thread, &Thread::m_wait_queue_node> ThreadList;
ThreadList m_threads;
}; };