Kernel: Rewrite scheduler thread lists
Scheduler now has its own data SchedulerQueue which holds active nad blocking thread lists. This removes need for BAN/Errors.h and making current thread separate element instead of iterator into linked list. This makes it possible to have current_thread on each processor instead of a global one in Scheduler.
This commit is contained in:
		
							parent
							
								
									1a1f9b1cf2
								
							
						
					
					
						commit
						e636dce919
					
				| 
						 | 
					@ -52,7 +52,8 @@ namespace Kernel
 | 
				
			||||||
		void exit(int status, int signal);
 | 
							void exit(int status, int signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void add_thread(Thread*);
 | 
							void add_thread(Thread*);
 | 
				
			||||||
		void on_thread_exit(Thread&);
 | 
							// returns true if thread was the last one
 | 
				
			||||||
 | 
							bool on_thread_exit(Thread&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pid_t sid() const { return m_sid; }
 | 
							pid_t sid() const { return m_sid; }
 | 
				
			||||||
		pid_t pgrp() const { return m_pgrp; }
 | 
							pid_t pgrp() const { return m_pgrp; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <BAN/LinkedList.h>
 | 
					#include <kernel/SchedulerQueue.h>
 | 
				
			||||||
#include <kernel/Semaphore.h>
 | 
					#include <kernel/Semaphore.h>
 | 
				
			||||||
#include <kernel/Thread.h>
 | 
					#include <kernel/Thread.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,6 @@ namespace Kernel
 | 
				
			||||||
		static pid_t current_tid();
 | 
							static pid_t current_tid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[noreturn]] void execute_current_thread();
 | 
							[[noreturn]] void execute_current_thread();
 | 
				
			||||||
		[[noreturn]] void execute_current_thread_locked();
 | 
					 | 
				
			||||||
		[[noreturn]] void delete_current_process_and_thread();
 | 
							[[noreturn]] void delete_current_process_and_thread();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// This is no return if called on current thread
 | 
							// This is no return if called on current thread
 | 
				
			||||||
| 
						 | 
					@ -41,34 +40,22 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void set_current_thread_sleeping_impl(uint64_t wake_time);
 | 
							void set_current_thread_sleeping_impl(uint64_t wake_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void wake_threads();
 | 
					 | 
				
			||||||
		[[nodiscard]] bool save_current_thread();
 | 
							[[nodiscard]] bool save_current_thread();
 | 
				
			||||||
		void remove_and_advance_current_thread();
 | 
					 | 
				
			||||||
		void advance_current_thread();
 | 
							void advance_current_thread();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[noreturn]] void execute_current_thread_locked();
 | 
				
			||||||
		[[noreturn]] void execute_current_thread_stack_loaded();
 | 
							[[noreturn]] void execute_current_thread_stack_loaded();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<void> add_thread(Thread*);
 | 
							BAN::ErrorOr<void> add_thread(Thread*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		struct SchedulerThread
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			SchedulerThread(Thread* thread)
 | 
					 | 
				
			||||||
				: thread(thread)
 | 
					 | 
				
			||||||
			{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Thread*		thread;
 | 
					 | 
				
			||||||
			uint64_t	wake_time;
 | 
					 | 
				
			||||||
			Semaphore*	semaphore;
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		SpinLock m_lock;
 | 
							SpinLock m_lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Thread* m_idle_thread { nullptr };
 | 
							SchedulerQueue m_active_threads;
 | 
				
			||||||
		BAN::LinkedList<SchedulerThread> m_active_threads;
 | 
							SchedulerQueue m_blocking_threads;
 | 
				
			||||||
		BAN::LinkedList<SchedulerThread> m_sleeping_threads;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::LinkedList<SchedulerThread>::iterator m_current_thread;
 | 
							Thread* m_idle_thread { nullptr };
 | 
				
			||||||
 | 
							SchedulerQueue::Node* m_current_thread { nullptr };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		friend class Process;
 | 
							friend class Process;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,126 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <BAN/Assert.h>
 | 
				
			||||||
 | 
					#include <BAN/NoCopyMove.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Kernel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class Thread;
 | 
				
			||||||
 | 
						class Semaphore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class SchedulerQueue
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							BAN_NON_COPYABLE(SchedulerQueue);
 | 
				
			||||||
 | 
							BAN_NON_MOVABLE(SchedulerQueue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							struct Node
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Node(Thread* thread)
 | 
				
			||||||
 | 
									: thread(thread)
 | 
				
			||||||
 | 
								{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Thread*		thread;
 | 
				
			||||||
 | 
								uint64_t	wake_time { 0 };
 | 
				
			||||||
 | 
								Semaphore*	semaphore { nullptr };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private:
 | 
				
			||||||
 | 
								Node* next { nullptr };
 | 
				
			||||||
 | 
								friend class SchedulerQueue;
 | 
				
			||||||
 | 
								friend class Scheduler;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							SchedulerQueue() = default;
 | 
				
			||||||
 | 
							~SchedulerQueue() { ASSERT_NOT_REACHED(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool empty() const { return m_front == nullptr; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Node* pop_front()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ASSERT(!empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Node* node = m_front;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m_front = m_front->next;
 | 
				
			||||||
 | 
								if (m_front == nullptr)
 | 
				
			||||||
 | 
									m_back = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								node->next = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return node;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void push_back(Node* node)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ASSERT(node);
 | 
				
			||||||
 | 
								node->next = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								(empty() ? m_front : m_back->next) = node;
 | 
				
			||||||
 | 
								m_back = node;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void add_with_wake_time(Node* node)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ASSERT(node);
 | 
				
			||||||
 | 
								node->next = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (empty() || node->wake_time >= m_back->wake_time)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									push_back(node);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (node->wake_time < m_front->wake_time)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									node->next = m_front;
 | 
				
			||||||
 | 
									m_front = node;
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Node* prev = m_front;
 | 
				
			||||||
 | 
								for (; node->wake_time >= prev->next->wake_time; prev = prev->next)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								node->next = prev->next;
 | 
				
			||||||
 | 
								prev->next = node;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void remove_with_wake_time(SchedulerQueue& out, uint64_t current_time)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								while (!empty() && m_front->wake_time <= current_time)
 | 
				
			||||||
 | 
									out.push_back(pop_front());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							template<typename F>
 | 
				
			||||||
 | 
							void remove_with_condition(SchedulerQueue& out, F comp)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								while (!empty() && comp(m_front))
 | 
				
			||||||
 | 
									out.push_back(pop_front());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (empty())
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (Node* prev = m_front; prev->next;)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Node* node = prev->next;
 | 
				
			||||||
 | 
									if (!comp(node))
 | 
				
			||||||
 | 
										prev = prev->next;
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										prev->next = node->next;
 | 
				
			||||||
 | 
										if (node == m_back)
 | 
				
			||||||
 | 
											m_back = prev;
 | 
				
			||||||
 | 
										out.push_back(node);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							Node* m_front { nullptr };
 | 
				
			||||||
 | 
							Node* m_back { nullptr };
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -218,7 +218,7 @@ namespace Kernel
 | 
				
			||||||
		m_loadable_elf.clear();
 | 
							m_loadable_elf.clear();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Process::on_thread_exit(Thread& thread)
 | 
						bool Process::on_thread_exit(Thread& thread)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
 | 
							ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,9 +230,7 @@ namespace Kernel
 | 
				
			||||||
			m_threads.clear();
 | 
								m_threads.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			thread.setup_process_cleanup();
 | 
								thread.setup_process_cleanup();
 | 
				
			||||||
			// NOTE: This function is only called from scheduler when it is already locked
 | 
								return true;
 | 
				
			||||||
			Scheduler::get().execute_current_thread_locked();
 | 
					 | 
				
			||||||
			ASSERT_NOT_REACHED();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (size_t i = 0; i < m_threads.size(); i++)
 | 
							for (size_t i = 0; i < m_threads.size(); i++)
 | 
				
			||||||
| 
						 | 
					@ -240,7 +238,7 @@ namespace Kernel
 | 
				
			||||||
			if (m_threads[i] == &thread)
 | 
								if (m_threads[i] == &thread)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				m_threads.remove(i);
 | 
									m_threads.remove(i);
 | 
				
			||||||
				return;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ namespace Kernel
 | 
				
			||||||
		ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
 | 
							ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
 | 
				
			||||||
		m_lock.lock();
 | 
							m_lock.lock();
 | 
				
			||||||
		ASSERT(!m_active_threads.empty());
 | 
							ASSERT(!m_active_threads.empty());
 | 
				
			||||||
		m_current_thread = m_active_threads.begin();
 | 
							advance_current_thread();
 | 
				
			||||||
		execute_current_thread_locked();
 | 
							execute_current_thread_locked();
 | 
				
			||||||
		ASSERT_NOT_REACHED();
 | 
							ASSERT_NOT_REACHED();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ namespace Kernel
 | 
				
			||||||
	void Scheduler::timer_reschedule()
 | 
						void Scheduler::timer_reschedule()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto state = m_lock.lock();
 | 
							auto state = m_lock.lock();
 | 
				
			||||||
		wake_threads();
 | 
							m_blocking_threads.remove_with_wake_time(m_active_threads, SystemTimer::get().ms_since_boot());
 | 
				
			||||||
		if (save_current_thread())
 | 
							if (save_current_thread())
 | 
				
			||||||
			return Processor::set_interrupt_state(state);
 | 
								return Processor::set_interrupt_state(state);
 | 
				
			||||||
		advance_current_thread();
 | 
							advance_current_thread();
 | 
				
			||||||
| 
						 | 
					@ -83,34 +83,22 @@ namespace Kernel
 | 
				
			||||||
	void Scheduler::reschedule_if_idling()
 | 
						void Scheduler::reschedule_if_idling()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto state = m_lock.lock();
 | 
							auto state = m_lock.lock();
 | 
				
			||||||
		if (m_active_threads.empty() || ¤t_thread() != m_idle_thread)
 | 
							if (m_active_threads.empty() || m_current_thread)
 | 
				
			||||||
			return m_lock.unlock(state);
 | 
								return m_lock.unlock(state);
 | 
				
			||||||
		if (save_current_thread())
 | 
							if (save_current_thread())
 | 
				
			||||||
			return Processor::set_interrupt_state(state);
 | 
								return Processor::set_interrupt_state(state);
 | 
				
			||||||
		m_current_thread = m_active_threads.begin();
 | 
							advance_current_thread();
 | 
				
			||||||
		execute_current_thread_locked();
 | 
							execute_current_thread_locked();
 | 
				
			||||||
		ASSERT_NOT_REACHED();
 | 
							ASSERT_NOT_REACHED();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Scheduler::wake_threads()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ASSERT(m_lock.current_processor_has_lock());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		uint64_t current_time = SystemTimer::get().ms_since_boot();
 | 
					 | 
				
			||||||
		while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			m_sleeping_threads.move_element_to_other_linked_list(
 | 
					 | 
				
			||||||
				m_active_threads,
 | 
					 | 
				
			||||||
				m_active_threads.end(),
 | 
					 | 
				
			||||||
				m_sleeping_threads.begin()
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
 | 
						BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							auto* node = new SchedulerQueue::Node(thread);
 | 
				
			||||||
 | 
							if (node == nullptr)
 | 
				
			||||||
 | 
								return BAN::Error::from_errno(ENOMEM);
 | 
				
			||||||
		SpinLockGuard _(m_lock);
 | 
							SpinLockGuard _(m_lock);
 | 
				
			||||||
		TRY(m_active_threads.emplace_back(thread));
 | 
							m_active_threads.push_back(node);
 | 
				
			||||||
		return {};
 | 
							return {};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,32 +114,12 @@ namespace Kernel
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ASSERT(m_lock.current_processor_has_lock());
 | 
							ASSERT(m_lock.current_processor_has_lock());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (m_active_threads.empty())
 | 
							if (m_current_thread)
 | 
				
			||||||
		{
 | 
								m_active_threads.push_back(m_current_thread);
 | 
				
			||||||
			m_current_thread = {};
 | 
							m_current_thread = nullptr;
 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (!m_current_thread || ++m_current_thread == m_active_threads.end())
 | 
					 | 
				
			||||||
			m_current_thread = m_active_threads.begin();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Scheduler::remove_and_advance_current_thread()
 | 
							if (!m_active_threads.empty())
 | 
				
			||||||
	{
 | 
								m_current_thread = m_active_threads.pop_front();
 | 
				
			||||||
		ASSERT(m_lock.current_processor_has_lock());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ASSERT(m_current_thread);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (m_active_threads.size() == 1)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			m_active_threads.remove(m_current_thread);
 | 
					 | 
				
			||||||
			m_current_thread = {};
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto temp = m_current_thread;
 | 
					 | 
				
			||||||
			advance_current_thread();
 | 
					 | 
				
			||||||
			m_active_threads.remove(temp);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// NOTE: this is declared always inline, so we don't corrupt the stack
 | 
						// NOTE: this is declared always inline, so we don't corrupt the stack
 | 
				
			||||||
| 
						 | 
					@ -189,11 +157,11 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ASSERT(thread->has_process());
 | 
							ASSERT(thread->has_process());
 | 
				
			||||||
		delete &thread->process();
 | 
							delete &thread->process();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		remove_and_advance_current_thread();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		delete thread;
 | 
							delete thread;
 | 
				
			||||||
 | 
							delete m_current_thread;
 | 
				
			||||||
 | 
							m_current_thread = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							advance_current_thread();
 | 
				
			||||||
		execute_current_thread_locked();
 | 
							execute_current_thread_locked();
 | 
				
			||||||
		ASSERT_NOT_REACHED();
 | 
							ASSERT_NOT_REACHED();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -244,12 +212,14 @@ namespace Kernel
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Thread* thread = m_current_thread->thread;
 | 
								Thread* thread = m_current_thread->thread;
 | 
				
			||||||
			if (thread->has_process())
 | 
								if (thread->has_process())
 | 
				
			||||||
				thread->process().on_thread_exit(*thread);
 | 
									if (thread->process().on_thread_exit(*thread))
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
			remove_and_advance_current_thread();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			delete thread;
 | 
								delete thread;
 | 
				
			||||||
 | 
								delete m_current_thread;
 | 
				
			||||||
 | 
								m_current_thread = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								advance_current_thread();
 | 
				
			||||||
			current = ¤t_thread();
 | 
								current = ¤t_thread();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -286,21 +256,11 @@ namespace Kernel
 | 
				
			||||||
		if (save_current_thread())
 | 
							if (save_current_thread())
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto it = m_sleeping_threads.begin();
 | 
					 | 
				
			||||||
		for (; it != m_sleeping_threads.end(); it++)
 | 
					 | 
				
			||||||
			if (wake_time <= it->wake_time)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		m_current_thread->wake_time = wake_time;
 | 
							m_current_thread->wake_time = wake_time;
 | 
				
			||||||
		m_active_threads.move_element_to_other_linked_list(
 | 
							m_blocking_threads.add_with_wake_time(m_current_thread);
 | 
				
			||||||
			m_sleeping_threads,
 | 
							m_current_thread = nullptr;
 | 
				
			||||||
			it,
 | 
					 | 
				
			||||||
			m_current_thread
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m_current_thread = {};
 | 
					 | 
				
			||||||
		advance_current_thread();
 | 
							advance_current_thread();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		execute_current_thread_locked();
 | 
							execute_current_thread_locked();
 | 
				
			||||||
		ASSERT_NOT_REACHED();
 | 
							ASSERT_NOT_REACHED();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -324,40 +284,13 @@ namespace Kernel
 | 
				
			||||||
	void Scheduler::unblock_threads(Semaphore* semaphore)
 | 
						void Scheduler::unblock_threads(Semaphore* semaphore)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		SpinLockGuard _(m_lock);
 | 
							SpinLockGuard _(m_lock);
 | 
				
			||||||
 | 
							m_blocking_threads.remove_with_condition(m_active_threads, [&](auto* node) { return node->semaphore == semaphore; });
 | 
				
			||||||
		for (auto it = m_sleeping_threads.begin(); it != m_sleeping_threads.end();)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (it->semaphore == semaphore)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				it = m_sleeping_threads.move_element_to_other_linked_list(
 | 
					 | 
				
			||||||
					m_active_threads,
 | 
					 | 
				
			||||||
					m_active_threads.end(),
 | 
					 | 
				
			||||||
					it
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				it++;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Scheduler::unblock_thread(pid_t tid)
 | 
						void Scheduler::unblock_thread(pid_t tid)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		SpinLockGuard _(m_lock);
 | 
							SpinLockGuard _(m_lock);
 | 
				
			||||||
 | 
							m_blocking_threads.remove_with_condition(m_active_threads, [&](auto* node) { return node->thread->tid() == tid; });
 | 
				
			||||||
		for (auto it = m_sleeping_threads.begin(); it != m_sleeping_threads.end(); it++)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (it->thread->tid() == tid)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				m_sleeping_threads.move_element_to_other_linked_list(
 | 
					 | 
				
			||||||
					m_active_threads,
 | 
					 | 
				
			||||||
					m_active_threads.end(),
 | 
					 | 
				
			||||||
					it
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue