kernel: Change the timer subsystem to use timespecs natively
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-06-03 13:15:10 +02:00
parent d2334a67dd
commit 8bcec00a9d
Signed by: apio
GPG Key ID: B8A7D06E42258954
7 changed files with 40 additions and 92 deletions

View File

@ -35,7 +35,9 @@ static void log_serial(LogLevel level, const char* format, va_list origin)
"\x1b[0m ",
ansi_color_codes_per_log_level[(int)level], log_level_letters[(int)level]);
Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000));
auto* time = Timer::monotonic_clock();
Serial::printf("%4zu.%.3zu ", time->tv_sec, time->tv_nsec / 1'000'000);
// NOTE: We do this manually because of a lack of vprintf() in both Serial and TextConsole.
cstyle_format(

View File

@ -4,10 +4,8 @@
#include "boot/bootboot.h"
#include <luna/TypeTraits.h>
// NOTE: Storing these values as unsigned integers doesn't allow for pre-epoch times.
// We are in 2023 anyway, not sure why anybody would want to set their computer's time to 1945.
static u64 timer_ticks = 0;
static u64 boot_timestamp;
static struct timespec s_monotonic_clock = { 0, 0 };
static struct timespec s_realtime_clock;
static inline constexpr bool isleap(u32 year)
{
@ -56,84 +54,33 @@ extern const BOOTBOOT bootboot;
namespace Timer
{
static struct timespec s_interval = { .tv_sec = 0, .tv_nsec = ARCH_TIMER_RESOLUTION * 1000 };
void tick()
{
timer_ticks += ARCH_TIMER_RESOLUTION;
timespecadd(&s_monotonic_clock, &s_interval, &s_monotonic_clock);
timespecadd(&s_realtime_clock, &s_interval, &s_realtime_clock);
}
usize raw_ticks()
struct timespec* monotonic_clock()
{
return timer_ticks;
return &s_monotonic_clock;
}
usize ticks()
struct timespec* realtime_clock()
{
return ticks_us() / US_PER_SECOND;
}
usize ticks_ms()
{
return timer_ticks / 1000;
}
usize ticks_us()
{
return timer_ticks;
}
usize ticks_ns()
{
return ticks_us() * 1000;
}
usize boot()
{
return boot_timestamp / US_PER_SECOND;
}
usize boot_ms()
{
return boot_timestamp / 1000;
}
usize boot_us()
{
return boot_timestamp;
}
usize boot_ns()
{
return boot_timestamp * 1000;
}
usize clock()
{
return boot() + ticks();
}
usize clock_ms()
{
return boot_ms() + ticks_ms();
}
usize clock_us()
{
return boot_us() + ticks_us();
}
usize clock_ns()
{
return boot_ns() + ticks_ns();
return &s_realtime_clock;
}
void init()
{
boot_timestamp = bootloader_time_to_unix(bootboot.datetime) * US_PER_SECOND;
s_realtime_clock.tv_sec = bootloader_time_to_unix(bootboot.datetime);
s_realtime_clock.tv_nsec = 0;
arch_init();
}
}
bool should_invoke_scheduler()
{
return (timer_ticks % 1000) == 0;
return (s_realtime_clock.tv_nsec % 1'000'000) == 0;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <bits/timespec.h>
#include <luna/Types.h>
#ifdef ARCH_X86_64
@ -15,22 +16,9 @@ namespace Timer
{
void tick();
usize raw_ticks();
struct timespec* monotonic_clock();
usize ticks();
usize ticks_ms();
usize ticks_us();
usize ticks_ns();
usize boot();
usize boot_ms();
usize boot_us();
usize boot_ns();
usize clock();
usize clock_ms();
usize clock_us();
usize clock_ns();
struct timespec* realtime_clock();
void arch_init();
void init();

View File

@ -2,4 +2,5 @@
#include <luna/Types.h>
// Every timer tick is equivalent to 250 microseconds.
// FIXME: Change ARCH_TIMER_RESOLUTION to use nanoseconds.
const usize ARCH_TIMER_RESOLUTION = 250;

View File

@ -12,19 +12,11 @@ Result<u64> sys_clock_gettime(Registers*, SyscallArgs args)
switch (id)
{
case CLOCK_MONOTONIC: {
usize ticks = Timer::ticks_ns();
struct timespec kernel_ts;
kernel_ts.tv_sec = (time_t)(ticks / NS_PER_SECOND);
kernel_ts.tv_nsec = (long)(ticks % NS_PER_SECOND);
if (!MemoryManager::copy_to_user_typed(ts, &kernel_ts)) return err(EFAULT);
if (!MemoryManager::copy_to_user_typed(ts, Timer::monotonic_clock())) return err(EFAULT);
break;
}
case CLOCK_REALTIME: {
usize clock = Timer::clock_ns();
struct timespec kernel_ts;
kernel_ts.tv_sec = (time_t)(clock / NS_PER_SECOND);
kernel_ts.tv_nsec = (long)(clock % NS_PER_SECOND);
if (!MemoryManager::copy_to_user_typed(ts, &kernel_ts)) return err(EFAULT);
if (!MemoryManager::copy_to_user_typed(ts, Timer::realtime_clock())) return err(EFAULT);
break;
}
default: return err(EINVAL);

View File

@ -18,3 +18,19 @@ struct timeval
};
#endif
#if defined(IN_MOON) || defined(_INCLUDE_TIMESPEC_MACROS)
#ifndef _TIMESPEC_MACROS_INCLUDED
#define _TIMESPEC_MACROS_INCLUDED
#define timespecadd(a, b, res) \
do { \
(res)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(res)->tv_nsec = (a)->tv_nsec + (b)->tv_nsec; \
while ((res)->tv_nsec >= 1'000'000'000) \
{ \
(res)->tv_sec++; \
(res)->tv_nsec -= 1'000'000'000; \
} \
} while (0);
#endif
#endif

View File

@ -3,6 +3,8 @@
#ifndef _SYS_TIME_H
#define _SYS_TIME_H
#define _INCLUDE_TIMESPEC_MACROS
#include <bits/attrs.h>
#include <bits/timespec.h>