Kernel: Scheduler sleeping is working

We have to disable optimization for one function, but I'm working
on a fix
This commit is contained in:
Bananymous 2023-03-07 23:22:25 +02:00
parent b8ee77eb78
commit 0b62729887
3 changed files with 51 additions and 40 deletions

View File

@ -24,11 +24,11 @@
namespace PIT namespace PIT
{ {
static uint64_t s_system_time = 0; static volatile uint64_t s_system_time = 0;
void irq_handler() void irq_handler()
{ {
s_system_time++; s_system_time = s_system_time + 1;
Kernel::Scheduler::get().reschedule(); Kernel::Scheduler::get().reschedule();
} }
@ -55,7 +55,10 @@ namespace PIT
{ {
if (ms == 0) if (ms == 0)
return; return;
Kernel::Scheduler::get().set_current_thread_sleeping(ms); uint64_t wake_time = s_system_time + ms;
Kernel::Scheduler::get().set_current_thread_sleeping(wake_time);
if (s_system_time < wake_time)
dwarnln("sleep woke {} ms too soon", wake_time - s_system_time);
} }
} }

View File

@ -54,9 +54,9 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
BAN::RefCounted<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()
@ -68,13 +68,11 @@ namespace Kernel
return; return;
m_last_reschedule = PIT::ms_since_boot(); m_last_reschedule = PIT::ms_since_boot();
if (!m_sleeping_threads.empty())
m_sleeping_threads.front().wake_delta--;
wake_threads(); wake_threads();
if (save_current_thread()) if (save_current_thread())
return; return;
get_next_thread(); advance_current_thread();
execute_current_thread(); execute_current_thread();
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@ -83,7 +81,8 @@ namespace Kernel
{ {
VERIFY_CLI(); VERIFY_CLI();
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_delta == 0) uint64_t current_time = PIT::ms_since_boot();
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
{ {
auto thread = m_sleeping_threads.front().thread; auto thread = m_sleeping_threads.front().thread;
m_sleeping_threads.remove(m_sleeping_threads.begin()); m_sleeping_threads.remove(m_sleeping_threads.begin());
@ -109,7 +108,7 @@ namespace Kernel
return {}; return {};
} }
void Scheduler::get_next_thread() void Scheduler::advance_current_thread()
{ {
VERIFY_CLI(); VERIFY_CLI();
@ -118,11 +117,29 @@ namespace Kernel
m_current_thread = {}; m_current_thread = {};
return; return;
} }
if (!m_current_thread || ++m_current_thread == m_active_threads.end()) if (!m_current_thread || ++m_current_thread == m_active_threads.end())
m_current_thread = m_active_threads.begin(); m_current_thread = m_active_threads.begin();
} }
void Scheduler::remove_and_advance_current_thread()
{
VERIFY_CLI();
ASSERT(m_current_thread);
if (m_active_threads.size() == 1)
{
m_active_threads.remove(m_current_thread);
m_current_thread = {};
}
else
{
auto temp = m_current_thread;
advance_current_thread();
m_active_threads.remove(temp);
}
}
// NOTE: this is declared always inline, so we don't corrupt the stack // NOTE: this is declared always inline, so we don't corrupt the stack
// after getting the rsp // after getting the rsp
ALWAYS_INLINE bool Scheduler::save_current_thread() ALWAYS_INLINE bool Scheduler::save_current_thread()
@ -138,9 +155,9 @@ namespace Kernel
} }
read_rsp(rsp); read_rsp(rsp);
auto current = current_thread(); auto& current = current_thread();
current->set_rip(rip); current.set_rip(rip);
current->set_rsp(rsp); current.set_rsp(rsp);
return false; return false;
} }
@ -148,64 +165,56 @@ namespace Kernel
{ {
VERIFY_CLI(); VERIFY_CLI();
auto current = current_thread(); auto& current = current_thread();
if (current->started()) if (current.started())
{ {
continue_thread(current->rsp(), current->rip()); continue_thread(current.rsp(), current.rip());
} }
else else
{ {
current->set_started(); current.set_started();
start_thread(current->function(), current->rsp(), current->rip()); start_thread(current.function(), current.rsp(), current.rip());
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void Scheduler::set_current_thread_sleeping(uint64_t wake_delta) #pragma GCC push_options
#pragma GCC optimize("O0")
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
{ {
DISABLE_INTERRUPTS(); DISABLE_INTERRUPTS();
ASSERT(m_current_thread); ASSERT(m_current_thread);
auto current = m_current_thread->thread; auto sleeping = m_current_thread->thread;
auto temp = m_current_thread;
if (save_current_thread()) if (save_current_thread())
return; return;
get_next_thread(); remove_and_advance_current_thread();
m_active_threads.remove(temp);
auto it = m_sleeping_threads.begin(); auto it = m_sleeping_threads.begin();
for (; it != m_sleeping_threads.end(); it++) for (; it != m_sleeping_threads.end(); it++)
{ if (wake_time <= it->wake_time)
if (wake_delta <= it->wake_delta)
break; break;
wake_delta -= it->wake_delta;
}
if (it != m_sleeping_threads.end())
it->wake_delta -= wake_delta;
// 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.insert(it, { current, wake_delta })); 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()
{ {
DISABLE_INTERRUPTS(); DISABLE_INTERRUPTS();
ASSERT(m_current_thread); ASSERT(m_current_thread);
remove_and_advance_current_thread();
auto temp = m_current_thread;
get_next_thread();
m_active_threads.remove(temp);
execute_current_thread(); execute_current_thread();
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();

View File

@ -59,8 +59,7 @@ namespace Kernel
TTY_PRINT("{}", m_prompt); TTY_PRINT("{}", m_prompt);
for (;;) for (;;)
{ {
//PIT::sleep(1); // sleep until next reschedule PIT::sleep(1); // sleep until next reschedule
asm volatile("hlt");
Input::update(); Input::update();
} }
} }