2023-02-01 01:53:35 +02:00
|
|
|
#pragma once
|
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
#include <BAN/Array.h>
|
|
|
|
#include <BAN/ForwardList.h>
|
|
|
|
#include <BAN/NoCopyMove.h>
|
|
|
|
#include <kernel/InterruptStack.h>
|
2024-07-24 00:31:01 +03:00
|
|
|
#include <kernel/ProcessorID.h>
|
2024-07-22 00:33:50 +03:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
2023-02-01 01:53:35 +02:00
|
|
|
|
|
|
|
namespace Kernel
|
|
|
|
{
|
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
class Thread;
|
|
|
|
class ThreadBlocker;
|
|
|
|
|
|
|
|
class SchedulerQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Node
|
|
|
|
{
|
|
|
|
Node(Thread* thread)
|
|
|
|
: thread(thread)
|
|
|
|
{}
|
|
|
|
|
2024-07-24 00:31:01 +03:00
|
|
|
Thread* const thread;
|
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
Node* next { nullptr };
|
|
|
|
Node* prev { nullptr };
|
|
|
|
|
|
|
|
uint64_t wake_time_ns { static_cast<uint64_t>(-1) };
|
|
|
|
|
2024-07-24 00:31:01 +03:00
|
|
|
ThreadBlocker* blocker { nullptr };
|
|
|
|
Node* block_chain_next { nullptr };
|
|
|
|
Node* block_chain_prev { nullptr };
|
|
|
|
|
|
|
|
ProcessorID processor_id { PROCESSOR_NONE };
|
|
|
|
bool blocked { false };
|
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
uint64_t last_start_ns { 0 };
|
|
|
|
uint64_t time_used_ns { 0 };
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
void add_thread_to_back(Node*);
|
|
|
|
void add_thread_with_wake_time(Node*);
|
|
|
|
template<typename F>
|
|
|
|
Node* remove_with_condition(F callback);
|
|
|
|
void remove_node(Node*);
|
|
|
|
Node* front();
|
|
|
|
Node* pop_front();
|
|
|
|
|
|
|
|
bool empty() const { return m_head == nullptr; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Node* m_head { nullptr };
|
|
|
|
Node* m_tail { nullptr };
|
|
|
|
};
|
|
|
|
|
2023-02-01 01:53:35 +02:00
|
|
|
class Scheduler
|
|
|
|
{
|
2024-07-22 00:33:50 +03:00
|
|
|
BAN_NON_COPYABLE(Scheduler);
|
|
|
|
BAN_NON_MOVABLE(Scheduler);
|
|
|
|
|
2023-02-01 01:53:35 +02:00
|
|
|
public:
|
2024-07-22 00:33:50 +03:00
|
|
|
struct NewThreadRequest
|
|
|
|
{
|
|
|
|
SchedulerQueue::Node* node;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UnblockRequest
|
|
|
|
{
|
2024-07-24 00:31:01 +03:00
|
|
|
SchedulerQueue::Node* node;
|
2024-07-22 00:33:50 +03:00
|
|
|
};
|
2023-02-02 23:24:12 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
public:
|
|
|
|
static BAN::ErrorOr<Scheduler*> create();
|
|
|
|
BAN::ErrorOr<void> initialize();
|
2023-06-09 00:47:17 +03:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
void reschedule(InterruptStack*, InterruptRegisters*);
|
|
|
|
void reschedule_if_idle();
|
2024-03-29 18:02:12 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
void timer_interrupt();
|
2023-02-02 23:24:12 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
BAN::ErrorOr<void> add_thread(Thread*);
|
2023-04-12 17:49:04 +03:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns);
|
2024-07-24 00:31:01 +03:00
|
|
|
void unblock_thread(Thread*);
|
2023-03-30 18:45:47 +03:00
|
|
|
|
2023-03-30 19:13:28 +03:00
|
|
|
Thread& current_thread();
|
2024-07-22 00:33:50 +03:00
|
|
|
Thread& idle_thread();
|
2023-03-16 12:17:04 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
pid_t current_tid() const;
|
|
|
|
bool is_idle() const;
|
2024-03-01 15:49:39 +02:00
|
|
|
|
2023-02-01 01:53:35 +02:00
|
|
|
private:
|
2023-03-07 19:17:49 +02:00
|
|
|
Scheduler() = default;
|
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
void add_current_to_most_loaded(SchedulerQueue* target_queue);
|
|
|
|
void update_most_loaded_node_queue(SchedulerQueue::Node*, SchedulerQueue* target_queue);
|
|
|
|
void remove_node_from_most_loaded(SchedulerQueue::Node*);
|
2024-02-09 15:18:34 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
void do_load_balancing();
|
2024-03-01 15:49:39 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
class ProcessorID find_least_loaded_processor() const;
|
|
|
|
|
2024-07-24 00:31:01 +03:00
|
|
|
void add_thread(SchedulerQueue::Node*);
|
|
|
|
void unblock_thread(SchedulerQueue::Node*);
|
2023-04-19 00:39:06 +03:00
|
|
|
|
2023-02-01 01:53:35 +02:00
|
|
|
private:
|
2024-07-22 00:33:50 +03:00
|
|
|
SchedulerQueue m_run_queue;
|
|
|
|
SchedulerQueue m_block_queue;
|
|
|
|
SchedulerQueue::Node* m_current { nullptr };
|
|
|
|
|
|
|
|
uint32_t m_thread_count { 0 };
|
|
|
|
|
|
|
|
InterruptStack* m_interrupt_stack { nullptr };
|
|
|
|
InterruptRegisters* m_interrupt_registers { nullptr };
|
|
|
|
|
|
|
|
uint64_t m_last_reschedule_ns { 0 };
|
|
|
|
uint64_t m_last_load_balance_ns { 0 };
|
|
|
|
|
|
|
|
struct ThreadInfo
|
|
|
|
{
|
|
|
|
SchedulerQueue* queue { nullptr };
|
|
|
|
SchedulerQueue::Node* node { nullptr };
|
|
|
|
};
|
|
|
|
BAN::Array<ThreadInfo, 10> m_most_loaded_threads;
|
|
|
|
|
|
|
|
uint64_t m_idle_start_ns { 0 };
|
|
|
|
uint64_t m_idle_ns { 0 };
|
|
|
|
|
|
|
|
bool m_should_calculate_max_load_threads { true };
|
2024-03-01 15:49:39 +02:00
|
|
|
|
2024-07-22 00:33:50 +03:00
|
|
|
Thread* m_idle_thread { nullptr };
|
2023-03-07 19:17:49 +02:00
|
|
|
|
2024-07-24 00:31:01 +03:00
|
|
|
friend class ThreadBlocker;
|
2024-07-22 00:33:50 +03:00
|
|
|
friend class Processor;
|
2023-02-01 01:53:35 +02:00
|
|
|
};
|
|
|
|
|
2024-01-24 14:43:46 +02:00
|
|
|
}
|