Kernel: Rewrite ThreadBlocker

This gets rid of a very old bug where kernel panics when thread is being
woken up and unblocked at the same time on different cores. This
required adding a new lock to SchedulerQueue::Node and adding a cap to
how many threads a threadblocker can simultaneously block. I don't think
I ever block more than five threads on the same ThreadBlocker so this
should be fine.
This commit is contained in:
2025-07-01 18:15:27 +03:00
parent 41e1819072
commit 92e4078287
5 changed files with 85 additions and 70 deletions

View File

@@ -14,33 +14,12 @@ namespace Kernel
class BaseMutex;
class Thread;
class ThreadBlocker;
struct SchedulerQueueNode;
class SchedulerQueue
{
public:
struct Node
{
Node(Thread* thread)
: thread(thread)
{}
Thread* const thread;
Node* next { nullptr };
Node* prev { nullptr };
uint64_t wake_time_ns { static_cast<uint64_t>(-1) };
ThreadBlocker* blocker { nullptr };
Node* block_chain_next { nullptr };
Node* block_chain_prev { nullptr };
ProcessorID processor_id { PROCESSOR_NONE };
bool blocked { false };
uint64_t last_start_ns { 0 };
uint64_t time_used_ns { 0 };
};
using Node = SchedulerQueueNode;
public:
void add_thread_to_back(Node*);

View File

@@ -0,0 +1,35 @@
#pragma once
#include <kernel/ProcessorID.h>
#include <kernel/Lock/SpinLock.h>
namespace Kernel
{
class Thread;
class ThreadBlocker;
struct SchedulerQueueNode
{
SchedulerQueueNode(Thread* thread)
: thread(thread)
{}
Thread* const thread;
SchedulerQueueNode* next { nullptr };
SchedulerQueueNode* prev { nullptr };
uint64_t wake_time_ns { static_cast<uint64_t>(-1) };
SpinLock blocker_lock;
ThreadBlocker* blocker { nullptr };
ProcessorID processor_id { PROCESSOR_NONE };
bool blocked { false };
uint64_t last_start_ns { 0 };
uint64_t time_used_ns { 0 };
};
}

View File

@@ -33,7 +33,9 @@ namespace Kernel
private:
SpinLock m_lock;
SchedulerQueue::Node* m_block_chain { nullptr };
SchedulerQueue::Node* m_block_chain[32] {};
size_t m_block_chain_length { 0 };
friend class Scheduler;
};