Compare commits

...

2 Commits

Author SHA1 Message Date
6cd25fb9b1
Check for runnable threads
All checks were successful
continuous-integration/drone/pr Build is passing
2022-12-07 15:17:20 +01:00
021ea1063b
Add a state to Thread 2022-12-07 15:14:58 +01:00
3 changed files with 28 additions and 9 deletions

View File

@ -43,7 +43,7 @@ void Thread::set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4)
void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs) void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs)
{ {
if (!old_thread->is_idle) memcpy(&old_thread->regs, regs, sizeof(Registers)); if (!old_thread->is_idle()) memcpy(&old_thread->regs, regs, sizeof(Registers));
memcpy(regs, &new_thread->regs, sizeof(Registers)); memcpy(regs, &new_thread->regs, sizeof(Registers));
} }

View File

@ -18,7 +18,7 @@ namespace Scheduler
g_idle.id = 0; g_idle.id = 0;
g_idle.init_regs_kernel(); g_idle.init_regs_kernel();
g_idle.set_ip((u64)CPU::idle_loop); g_idle.set_ip((u64)CPU::idle_loop);
g_idle.is_idle = true; g_idle.state = ThreadState::Idle;
g_idle.ticks_left = 1; g_idle.ticks_left = 1;
@ -86,24 +86,31 @@ namespace Scheduler
Thread* pick_task() Thread* pick_task()
{ {
Thread* old = g_current; Thread* old = g_current;
if (old->is_idle) if (old->is_idle())
{ {
auto maybe_first = g_threads.last(); auto maybe_last = g_threads.last();
if (maybe_first.has_error()) // No threads!! if (maybe_last.has_error()) // No threads!!
return &g_idle; return &g_idle;
g_current = old = maybe_first.value(); g_current = old = maybe_last.value();
} }
bool has_found_thread = false;
do { do {
auto maybe_next = g_threads.next(g_current); auto maybe_next = g_threads.next(g_current);
if (maybe_next.has_error()) g_current = g_threads.first().value(); if (maybe_next.has_error()) g_current = g_threads.first().value();
else else
g_current = maybe_next.value(); g_current = maybe_next.value();
if (true) // FIXME: Check if the current task is runnable. if (g_current->state == ThreadState::Runnable)
{
has_found_thread = true;
break; break;
}
} while (g_current != old); } while (g_current != old);
if (!has_found_thread) g_current = &g_idle;
return g_current; return g_current;
} }
@ -111,7 +118,7 @@ namespace Scheduler
{ {
if (old_thread != new_thread) switch_context(old_thread, new_thread, regs); if (old_thread != new_thread) switch_context(old_thread, new_thread, regs);
if (new_thread->is_idle) if (new_thread->is_idle())
{ {
new_thread->ticks_left = 1; // The idle task only runs for 1 tick so we can check for new runnable tasks new_thread->ticks_left = 1; // The idle task only runs for 1 tick so we can check for new runnable tasks
// as fast as possible. // as fast as possible.

View File

@ -10,6 +10,13 @@
#error "Unknown architecture." #error "Unknown architecture."
#endif #endif
enum class ThreadState
{
Idle,
Runnable,
Sleeping
};
struct Thread : public DoublyLinkedListNode<Thread> struct Thread : public DoublyLinkedListNode<Thread>
{ {
Registers regs; Registers regs;
@ -22,7 +29,12 @@ struct Thread : public DoublyLinkedListNode<Thread>
u64 ticks_left; u64 ticks_left;
bool is_idle = false; ThreadState state = ThreadState::Runnable;
bool is_idle()
{
return state == ThreadState::Idle;
}
void init_regs_kernel(); void init_regs_kernel();
void init_regs_user(); void init_regs_user();