kernel: Add a timer queue with more versatility than simple alarm()
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-11-03 19:53:34 +01:00
parent 54ec441000
commit dfebdce689
Signed by: apio
GPG Key ID: B8A7D06E42258954
6 changed files with 123 additions and 6 deletions

View File

@ -25,6 +25,7 @@ set(SOURCES
src/thread/Thread.cpp
src/thread/ThreadImage.cpp
src/thread/Scheduler.cpp
src/thread/Timer.cpp
src/sys/Syscall.cpp
src/sys/exit.cpp
src/sys/clock_gettime.cpp

View File

@ -1,6 +1,7 @@
#include "Pledge.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include "thread/Timer.h"
Result<u64> sys_alarm(Registers*, SyscallArgs args)
{
@ -10,9 +11,16 @@ Result<u64> sys_alarm(Registers*, SyscallArgs args)
TRY(check_pledge(current, Promise::p_stdio));
u64 time_left = current->alarm_ticks_left;
u64 ticks_left = current->timer ? current->timer->ticks_left() : 0;
current->alarm_ticks_left = seconds * 1000;
if (current->timer) Scheduler::remove_from_timer_queue(current->timer);
else
current->timer = TRY(make<Scheduler::Timer>());
return time_left * 1000;
current->timer->total_ticks = seconds * 1000;
current->timer->thread = current;
Scheduler::add_to_timer_queue(current->timer);
return ticks_left * 1000;
}

View File

@ -5,6 +5,7 @@
#include "binfmt/ELF.h"
#include "memory/MemoryManager.h"
#include "thread/ThreadImage.h"
#include "thread/Timer.h"
#include <luna/Alignment.h>
#include <luna/ScopeGuard.h>
#include <luna/Stack.h>
@ -216,6 +217,12 @@ namespace Scheduler
MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value();
}
if (thread->timer)
{
Scheduler::remove_from_timer_queue(thread->timer);
delete thread->timer;
}
delete thread;
CPU::enable_interrupts();
@ -293,6 +300,8 @@ namespace Scheduler
{
CPU::disable_interrupts();
tick_queue();
if (is_in_kernel(regs)) g_current->kernel_ticks_self++;
else
g_current->user_ticks_self++;
@ -305,8 +314,6 @@ namespace Scheduler
{
if (thread->sleep_ticks_left == 0 || --thread->sleep_ticks_left == 0) thread->wake_up();
}
if (thread->alarm_ticks_left && --thread->alarm_ticks_left == 0) thread->send_signal(SIGALRM);
}
if (!g_current->ticks_left) switch_task(regs);

View File

@ -19,6 +19,11 @@
#error "Unknown architecture."
#endif
namespace Scheduler
{
class Timer;
}
enum class ThreadState
{
None,
@ -60,7 +65,6 @@ struct Thread : public LinkedListNode<Thread>
u64 ticks_left;
u64 sleep_ticks_left;
u64 alarm_ticks_left { 0 };
int promises { -1 };
int execpromises { -1 };
@ -97,6 +101,8 @@ struct Thread : public LinkedListNode<Thread>
mode_t umask { 0 };
Scheduler::Timer* timer { nullptr };
StaticString<128> cmdline;
String current_directory_path = {};

View File

@ -0,0 +1,72 @@
#include "thread/Timer.h"
#include "Log.h"
static LinkedList<Scheduler::Timer> g_timer_queue;
namespace Scheduler
{
void add_to_timer_queue(Timer* timer)
{
timer->delta_ticks = timer->total_ticks;
for (auto* t : g_timer_queue)
{
if (timer->delta_ticks <= t->delta_ticks)
{
t->delta_ticks -= timer->delta_ticks;
g_timer_queue.add_before(t, timer);
return;
}
timer->delta_ticks -= t->delta_ticks;
}
g_timer_queue.append(timer);
}
void remove_from_timer_queue(Timer* timer)
{
auto maybe_next = g_timer_queue.next(timer);
if (maybe_next.has_value())
{
auto next = maybe_next.value();
next->delta_ticks += timer->delta_ticks;
}
g_timer_queue.remove(timer);
}
void tick_queue()
{
auto maybe_first = g_timer_queue.first();
if (!maybe_first.has_value()) return;
auto first = *maybe_first;
first->delta_ticks--;
LinkedList<Scheduler::Timer> timers_to_be_restarted;
g_timer_queue.delayed_for_each([&](Timer* t) {
if (t->delta_ticks == 0)
{
g_timer_queue.remove(t);
t->thread->send_signal(t->signo);
if (t->restart) timers_to_be_restarted.append(t);
return true;
}
return false;
});
timers_to_be_restarted.consume([](Timer* t) { add_to_timer_queue(t); });
}
u64 Timer::ticks_left()
{
u64 total = 0;
for (auto* t : g_timer_queue)
{
total += t->delta_ticks;
if (t == this) break;
}
return total;
}
}

23
kernel/src/thread/Timer.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "thread/Thread.h"
#include <luna/LinkedList.h>
namespace Scheduler
{
class Timer : public LinkedListNode<Timer>
{
public:
u64 delta_ticks;
u64 total_ticks;
Thread* thread;
int signo { SIGALRM };
bool restart { false };
u64 ticks_left();
};
void add_to_timer_queue(Timer* timer);
void remove_from_timer_queue(Timer* timer);
void tick_queue();
}