Files
banan-os/kernel/include/kernel/SchedulerThreadNode.h
T
Bananymous 2f25bfb2db Kernel: Use min heap for scheduler block list
This makes insertion to block list O(log n) instead of O(n) when
blocking with wake time. This is more heavy and currently slower than
the previous implementation, but that is just because we don't really
have too many threads running at any given time. This will be more
scalable in the future and even allows implementing priorities if I ever
wish so
2026-08-19 21:32:36 +03:00

97 lines
2.0 KiB
C++

#pragma once
#include <BAN/Atomic.h>
#include <BAN/NoCopyMove.h>
#include <kernel/ProcessorID.h>
namespace Kernel
{
class Thread;
class ThreadBlocker;
struct SchedulerThreadNode
{
SchedulerThreadNode(Thread* thread)
: thread(thread)
, heap({ nullptr, nullptr, nullptr })
{}
Thread* const thread;
union
{
struct
{
SchedulerThreadNode* next;
SchedulerThreadNode* prev;
} queue;
struct
{
SchedulerThreadNode* parent;
SchedulerThreadNode* lchild;
SchedulerThreadNode* rchild;
} heap;
};
uint64_t wake_time_ns { static_cast<uint64_t>(-1) };
BAN::Atomic<ThreadBlocker*> blocker { nullptr };
SchedulerThreadNode* block_chain_prev { nullptr };
SchedulerThreadNode* block_chain_next { nullptr };
ProcessorID processor_id { PROCESSOR_NONE };
bool blocked { false };
uint64_t last_start_ns { 0 };
uint64_t time_used_ns { 0 };
};
class SchedulerQueue
{
BAN_NON_COPYABLE(SchedulerQueue);
BAN_NON_MOVABLE(SchedulerQueue);
public:
SchedulerQueue() = default;
SchedulerThreadNode* front();
SchedulerThreadNode* pop_front();
void push(SchedulerThreadNode*);
void pop(SchedulerThreadNode*);
void walk(void (*)(const SchedulerThreadNode*, void*), void*) const;
bool empty() const { return m_head == nullptr; }
private:
SchedulerThreadNode* m_head { nullptr };
SchedulerThreadNode* m_tail { nullptr };
};
class SchedulerHeap
{
BAN_NON_COPYABLE(SchedulerHeap);
BAN_NON_MOVABLE(SchedulerHeap);
public:
SchedulerHeap() = default;
SchedulerThreadNode* front();
SchedulerThreadNode* pop_front();
void push(SchedulerThreadNode*);
void pop(SchedulerThreadNode*);
void walk(void (*)(const SchedulerThreadNode*, void*), void*) const;
bool empty() const { return m_root == nullptr; }
private:
void walk_impl(void (*)(const SchedulerThreadNode*, void*), void*, const SchedulerThreadNode*) const;
void swap_nodes(SchedulerThreadNode*, SchedulerThreadNode*);
private:
SchedulerThreadNode* m_root { nullptr };
SchedulerThreadNode* m_last { nullptr };
};
}