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:
@@ -52,7 +52,8 @@ namespace Kernel
|
||||
void exit(int status, int signal);
|
||||
|
||||
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 pgrp() const { return m_pgrp; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/LinkedList.h>
|
||||
#include <kernel/SchedulerQueue.h>
|
||||
#include <kernel/Semaphore.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace Kernel
|
||||
static pid_t current_tid();
|
||||
|
||||
[[noreturn]] void execute_current_thread();
|
||||
[[noreturn]] void execute_current_thread_locked();
|
||||
[[noreturn]] void delete_current_process_and_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 wake_threads();
|
||||
[[nodiscard]] bool save_current_thread();
|
||||
void remove_and_advance_current_thread();
|
||||
void advance_current_thread();
|
||||
|
||||
[[noreturn]] void execute_current_thread_locked();
|
||||
[[noreturn]] void execute_current_thread_stack_loaded();
|
||||
|
||||
BAN::ErrorOr<void> add_thread(Thread*);
|
||||
|
||||
private:
|
||||
struct SchedulerThread
|
||||
{
|
||||
SchedulerThread(Thread* thread)
|
||||
: thread(thread)
|
||||
{}
|
||||
|
||||
Thread* thread;
|
||||
uint64_t wake_time;
|
||||
Semaphore* semaphore;
|
||||
};
|
||||
|
||||
SpinLock m_lock;
|
||||
|
||||
Thread* m_idle_thread { nullptr };
|
||||
BAN::LinkedList<SchedulerThread> m_active_threads;
|
||||
BAN::LinkedList<SchedulerThread> m_sleeping_threads;
|
||||
SchedulerQueue m_active_threads;
|
||||
SchedulerQueue m_blocking_threads;
|
||||
|
||||
BAN::LinkedList<SchedulerThread>::iterator m_current_thread;
|
||||
Thread* m_idle_thread { nullptr };
|
||||
SchedulerQueue::Node* m_current_thread { nullptr };
|
||||
|
||||
friend class Process;
|
||||
};
|
||||
|
||||
126
kernel/include/kernel/SchedulerQueue.h
Normal file
126
kernel/include/kernel/SchedulerQueue.h
Normal file
@@ -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 };
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user