forked from Bananymous/banan-os
Kernel: Thread is no longer RefCounted
This makes developement with Scheduler much easier against compiler optimizations. I could now remove the pragma GCC optimize stuff.
This commit is contained in:
parent
c8f05b4a7a
commit
88ee35165f
|
@ -44,7 +44,7 @@ namespace Kernel
|
||||||
BAN::String working_directory() const;
|
BAN::String working_directory() const;
|
||||||
BAN::ErrorOr<void> set_working_directory(BAN::StringView);
|
BAN::ErrorOr<void> set_working_directory(BAN::StringView);
|
||||||
|
|
||||||
static BAN::RefPtr<Process> current() { return Thread::current()->process(); }
|
static BAN::RefPtr<Process> current() { return Thread::current().process(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Process(pid_t pid) : m_pid(pid) {}
|
Process(pid_t pid) : m_pid(pid) {}
|
||||||
|
@ -70,7 +70,7 @@ namespace Kernel
|
||||||
|
|
||||||
const pid_t m_pid = 0;
|
const pid_t m_pid = 0;
|
||||||
BAN::String m_working_directory;
|
BAN::String m_working_directory;
|
||||||
BAN::Vector<BAN::RefPtr<Thread>> m_threads;
|
BAN::Vector<Thread*> m_threads;
|
||||||
|
|
||||||
friend class BAN::RefPtr<Process>;
|
friend class BAN::RefPtr<Process>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Kernel
|
||||||
void start();
|
void start();
|
||||||
void reschedule();
|
void reschedule();
|
||||||
|
|
||||||
BAN::ErrorOr<void> add_thread(BAN::RefPtr<Thread>);
|
BAN::ErrorOr<void> add_thread(Thread*);
|
||||||
|
|
||||||
void set_current_thread_sleeping(uint64_t);
|
void set_current_thread_sleeping(uint64_t);
|
||||||
[[noreturn]] void set_current_thread_done();
|
[[noreturn]] void set_current_thread_done();
|
||||||
|
@ -25,7 +25,7 @@ namespace Kernel
|
||||||
void block_current_thread(Semaphore*);
|
void block_current_thread(Semaphore*);
|
||||||
void unblock_threads(Semaphore*);
|
void unblock_threads(Semaphore*);
|
||||||
|
|
||||||
BAN::RefPtr<Thread> current_thread();
|
Thread& current_thread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Scheduler() = default;
|
Scheduler() = default;
|
||||||
|
@ -39,27 +39,27 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
struct ActiveThread
|
struct ActiveThread
|
||||||
{
|
{
|
||||||
ActiveThread(const BAN::RefPtr<Thread>& thread) : thread(thread) {}
|
ActiveThread(Thread* thread) : thread(thread) {}
|
||||||
BAN::RefPtr<Thread> thread;
|
Thread* thread;
|
||||||
uint64_t padding = 0;
|
uint64_t padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SleepingThread
|
struct SleepingThread
|
||||||
{
|
{
|
||||||
SleepingThread(const BAN::RefPtr<Thread>& thread, uint64_t wake_time) : thread(thread), wake_time(wake_time) {}
|
SleepingThread(Thread* thread, uint64_t wake_time) : thread(thread), wake_time(wake_time) {}
|
||||||
BAN::RefPtr<Thread> thread;
|
Thread* thread;
|
||||||
uint64_t wake_time;
|
uint64_t wake_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlockingThread
|
struct BlockingThread
|
||||||
{
|
{
|
||||||
BlockingThread(const BAN::RefPtr<Thread>& thread, Semaphore* semaphore) : thread(thread), semaphore(semaphore) {}
|
BlockingThread(Thread* thread, Semaphore* semaphore) : thread(thread), semaphore(semaphore) {}
|
||||||
BAN::RefPtr<Thread> thread;
|
Thread* thread;
|
||||||
Semaphore* semaphore;
|
Semaphore* semaphore;
|
||||||
uint8_t padding[sizeof(uint64_t) - sizeof(Semaphore*)];
|
uint8_t padding[sizeof(uint64_t) - sizeof(Semaphore*)];
|
||||||
};
|
};
|
||||||
|
|
||||||
BAN::RefPtr<Thread> m_idle_thread;
|
Thread* m_idle_thread { nullptr };
|
||||||
BAN::LinkedList<ActiveThread> m_active_threads;
|
BAN::LinkedList<ActiveThread> m_active_threads;
|
||||||
BAN::LinkedList<SleepingThread> m_sleeping_threads;
|
BAN::LinkedList<SleepingThread> m_sleeping_threads;
|
||||||
BAN::LinkedList<BlockingThread> m_blocking_threads;
|
BAN::LinkedList<BlockingThread> m_blocking_threads;
|
||||||
|
|
|
@ -10,13 +10,16 @@ namespace Kernel
|
||||||
|
|
||||||
class Process;
|
class Process;
|
||||||
|
|
||||||
class Thread : public BAN::RefCounted<Thread>
|
class Thread
|
||||||
{
|
{
|
||||||
|
BAN_NON_COPYABLE(Thread);
|
||||||
|
BAN_NON_MOVABLE(Thread);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using entry_t = void(*)(void*);
|
using entry_t = void(*)(void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Thread>> create(entry_t, void* = nullptr, BAN::RefPtr<Process> = nullptr);
|
static BAN::ErrorOr<Thread*> create(entry_t, void* = nullptr, BAN::RefPtr<Process> = nullptr);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
pid_t tid() const { return m_tid; }
|
pid_t tid() const { return m_tid; }
|
||||||
|
@ -29,7 +32,7 @@ namespace Kernel
|
||||||
void set_started() { m_started = true; }
|
void set_started() { m_started = true; }
|
||||||
bool started() const { return m_started; }
|
bool started() const { return m_started; }
|
||||||
|
|
||||||
static BAN::RefPtr<Thread> current() ;
|
static Thread& current() ;
|
||||||
BAN::RefPtr<Process> process();
|
BAN::RefPtr<Process> process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -45,8 +48,6 @@ namespace Kernel
|
||||||
const pid_t m_tid = 0;
|
const pid_t m_tid = 0;
|
||||||
bool m_started = false;
|
bool m_started = false;
|
||||||
BAN::RefPtr<Process> m_process;
|
BAN::RefPtr<Process> m_process;
|
||||||
|
|
||||||
friend class BAN::RefPtr<Thread>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
auto thread = TRY(Thread::create(entry, data, this));
|
Thread* thread = TRY(Thread::create(entry, data, this));
|
||||||
TRY(m_threads.push_back(thread));
|
TRY(m_threads.push_back(thread));
|
||||||
if (auto res = Scheduler::get().add_thread(thread); res.is_error())
|
if (auto res = Scheduler::get().add_thread(thread); res.is_error())
|
||||||
{
|
{
|
||||||
|
@ -36,9 +36,8 @@ namespace Kernel
|
||||||
void Process::on_thread_exit(Thread& thread)
|
void Process::on_thread_exit(Thread& thread)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
dprintln("thread {} exit", thread.tid());
|
|
||||||
for (size_t i = 0; i < m_threads.size(); i++)
|
for (size_t i = 0; i < m_threads.size(); i++)
|
||||||
if (m_threads[i].ptr() == &thread)
|
if (m_threads[i] == &thread)
|
||||||
m_threads.remove(i);
|
m_threads.remove(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::RefPtr<Thread> Scheduler::current_thread()
|
Thread& Scheduler::current_thread()
|
||||||
{
|
{
|
||||||
return m_current_thread ? m_current_thread->thread : m_idle_thread;
|
return m_current_thread ? *m_current_thread->thread : *m_idle_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::reschedule()
|
void Scheduler::reschedule()
|
||||||
|
@ -77,17 +77,16 @@ namespace Kernel
|
||||||
uint64_t current_time = PIT::ms_since_boot();
|
uint64_t current_time = PIT::ms_since_boot();
|
||||||
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
|
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
|
||||||
{
|
{
|
||||||
auto thread = m_sleeping_threads.front().thread;
|
Thread* thread = m_sleeping_threads.front().thread;
|
||||||
m_sleeping_threads.remove(m_sleeping_threads.begin());
|
m_sleeping_threads.remove(m_sleeping_threads.begin());
|
||||||
|
|
||||||
// This should work as we released enough memory from sleeping thread
|
// This should work as we released enough memory from sleeping thread
|
||||||
static_assert(sizeof(ActiveThread) == sizeof(SleepingThread));
|
static_assert(sizeof(ActiveThread) == sizeof(SleepingThread));
|
||||||
MUST(m_active_threads.emplace_back(thread));
|
MUST(m_active_threads.emplace_back(thread));
|
||||||
thread.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Scheduler::add_thread(BAN::RefPtr<Thread> thread)
|
BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
|
||||||
{
|
{
|
||||||
Kernel::CriticalScope critical;
|
Kernel::CriticalScope critical;
|
||||||
TRY(m_active_threads.emplace_back(thread));
|
TRY(m_active_threads.emplace_back(thread));
|
||||||
|
@ -141,9 +140,9 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
read_rsp(rsp);
|
read_rsp(rsp);
|
||||||
|
|
||||||
auto current = current_thread();
|
Thread& current = current_thread();
|
||||||
current->set_rip(rip);
|
current.set_rip(rip);
|
||||||
current->set_rsp(rsp);
|
current.set_rsp(rsp);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +150,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
VERIFY_CLI();
|
VERIFY_CLI();
|
||||||
|
|
||||||
auto& current = *current_thread();
|
Thread& current = current_thread();
|
||||||
|
|
||||||
if (current.started())
|
if (current.started())
|
||||||
{
|
{
|
||||||
|
@ -166,8 +165,6 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC optimize("O0")
|
|
||||||
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
|
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
|
||||||
{
|
{
|
||||||
VERIFY_STI();
|
VERIFY_STI();
|
||||||
|
@ -175,7 +172,7 @@ namespace Kernel
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
auto sleeping = m_current_thread->thread;
|
Thread* sleeping = m_current_thread->thread;
|
||||||
|
|
||||||
if (save_current_thread())
|
if (save_current_thread())
|
||||||
{
|
{
|
||||||
|
@ -192,12 +189,10 @@ namespace Kernel
|
||||||
// This should work as we released enough memory from active thread
|
// This should work as we released enough memory from active thread
|
||||||
static_assert(sizeof(ActiveThread) == sizeof(SleepingThread));
|
static_assert(sizeof(ActiveThread) == sizeof(SleepingThread));
|
||||||
MUST(m_sleeping_threads.emplace(it, sleeping, wake_time));
|
MUST(m_sleeping_threads.emplace(it, sleeping, wake_time));
|
||||||
sleeping.clear();
|
|
||||||
|
|
||||||
execute_current_thread();
|
execute_current_thread();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
#pragma GCC pop_options
|
|
||||||
|
|
||||||
void Scheduler::set_current_thread_done()
|
void Scheduler::set_current_thread_done()
|
||||||
{
|
{
|
||||||
|
@ -205,14 +200,15 @@ namespace Kernel
|
||||||
DISABLE_INTERRUPTS();
|
DISABLE_INTERRUPTS();
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
|
Thread* thread = m_current_thread->thread;
|
||||||
remove_and_advance_current_thread();
|
remove_and_advance_current_thread();
|
||||||
|
delete thread;
|
||||||
|
|
||||||
execute_current_thread();
|
execute_current_thread();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC optimize("O0")
|
|
||||||
void Scheduler::block_current_thread(Semaphore* semaphore)
|
void Scheduler::block_current_thread(Semaphore* semaphore)
|
||||||
{
|
{
|
||||||
VERIFY_STI();
|
VERIFY_STI();
|
||||||
|
@ -220,7 +216,7 @@ namespace Kernel
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
auto blocking = m_current_thread->thread;
|
Thread* blocking = m_current_thread->thread;
|
||||||
|
|
||||||
if (save_current_thread())
|
if (save_current_thread())
|
||||||
{
|
{
|
||||||
|
@ -232,14 +228,12 @@ namespace Kernel
|
||||||
// This should work as we released enough memory from active thread
|
// This should work as we released enough memory from active thread
|
||||||
static_assert(sizeof(ActiveThread) == sizeof(BlockingThread));
|
static_assert(sizeof(ActiveThread) == sizeof(BlockingThread));
|
||||||
MUST(m_blocking_threads.emplace_back(blocking, semaphore));
|
MUST(m_blocking_threads.emplace_back(blocking, semaphore));
|
||||||
blocking.clear();
|
|
||||||
|
|
||||||
semaphore->m_blocked = true;
|
semaphore->m_blocked = true;
|
||||||
|
|
||||||
execute_current_thread();
|
execute_current_thread();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
#pragma GCC pop_options
|
|
||||||
|
|
||||||
void Scheduler::unblock_threads(Semaphore* semaphore)
|
void Scheduler::unblock_threads(Semaphore* semaphore)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Kernel
|
||||||
void RecursiveSpinLock::lock()
|
void RecursiveSpinLock::lock()
|
||||||
{
|
{
|
||||||
// FIXME: is this thread safe?
|
// FIXME: is this thread safe?
|
||||||
if (m_locker == Thread::current()->tid())
|
if (m_locker == Thread::current().tid())
|
||||||
{
|
{
|
||||||
m_lock_depth++;
|
m_lock_depth++;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
ASSERT(m_locker == 0);
|
ASSERT(m_locker == 0);
|
||||||
m_locker = Thread::current()->tid();
|
m_locker = Thread::current().tid();
|
||||||
m_lock_depth = 1;
|
m_lock_depth = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,12 @@ namespace Kernel
|
||||||
memcpy((void*)rsp, (void*)&value, size);
|
memcpy((void*)rsp, (void*)&value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(entry_t entry, void* data, BAN::RefPtr<Process> process)
|
BAN::ErrorOr<Thread*> Thread::create(entry_t entry, void* data, BAN::RefPtr<Process> process)
|
||||||
{
|
{
|
||||||
static pid_t next_tid = 1;
|
static pid_t next_tid = 1;
|
||||||
auto thread = TRY(BAN::RefPtr<Thread>::create(next_tid++, process));
|
auto* thread = new Thread(next_tid++, process);
|
||||||
|
if (thread == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
TRY(thread->initialize(entry, data));
|
TRY(thread->initialize(entry, data));
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +33,7 @@ namespace Kernel
|
||||||
: m_tid(tid), m_process(process)
|
: m_tid(tid), m_process(process)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BAN::RefPtr<Thread> Thread::current()
|
Thread& Thread::current()
|
||||||
{
|
{
|
||||||
return Scheduler::get().current_thread();
|
return Scheduler::get().current_thread();
|
||||||
}
|
}
|
||||||
|
@ -58,6 +60,7 @@ namespace Kernel
|
||||||
|
|
||||||
Thread::~Thread()
|
Thread::~Thread()
|
||||||
{
|
{
|
||||||
|
dprintln("thread {} exit", tid());
|
||||||
kfree(m_stack_base);
|
kfree(m_stack_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue