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 ", "\x1b[0m ",
ansi_color_codes_per_log_level[(int)level], log_level_letters[(int)level]); 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. // NOTE: We do this manually because of a lack of vprintf() in both Serial and TextConsole.
cstyle_format( cstyle_format(

View File

@ -4,10 +4,8 @@
#include "boot/bootboot.h" #include "boot/bootboot.h"
#include <luna/TypeTraits.h> #include <luna/TypeTraits.h>
// NOTE: Storing these values as unsigned integers doesn't allow for pre-epoch times. static struct timespec s_monotonic_clock = { 0, 0 };
// We are in 2023 anyway, not sure why anybody would want to set their computer's time to 1945. static struct timespec s_realtime_clock;
static u64 timer_ticks = 0;
static u64 boot_timestamp;
static inline constexpr bool isleap(u32 year) static inline constexpr bool isleap(u32 year)
{ {
@ -56,84 +54,33 @@ extern const BOOTBOOT bootboot;
namespace Timer namespace Timer
{ {
static struct timespec s_interval = { .tv_sec = 0, .tv_nsec = ARCH_TIMER_RESOLUTION * 1000 };
void tick() 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; return &s_realtime_clock;
}
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();
} }
void init() 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(); arch_init();
} }
} }
bool should_invoke_scheduler() 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 #pragma once
#include <bits/timespec.h>
#include <luna/Types.h> #include <luna/Types.h>
#ifdef ARCH_X86_64 #ifdef ARCH_X86_64
@ -15,22 +16,9 @@ namespace Timer
{ {
void tick(); void tick();
usize raw_ticks(); struct timespec* monotonic_clock();
usize ticks(); struct timespec* realtime_clock();
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();
void arch_init(); void arch_init();
void init(); void init();

View File

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

View File

@ -12,19 +12,11 @@ Result<u64> sys_clock_gettime(Registers*, SyscallArgs args)
switch (id) switch (id)
{ {
case CLOCK_MONOTONIC: { case CLOCK_MONOTONIC: {
usize ticks = Timer::ticks_ns(); if (!MemoryManager::copy_to_user_typed(ts, Timer::monotonic_clock())) return err(EFAULT);
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);
break; break;
} }
case CLOCK_REALTIME: { case CLOCK_REALTIME: {
usize clock = Timer::clock_ns(); if (!MemoryManager::copy_to_user_typed(ts, Timer::realtime_clock())) return err(EFAULT);
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);
break; break;
} }
default: return err(EINVAL); default: return err(EINVAL);

View File

@ -18,3 +18,19 @@ struct timeval
}; };
#endif #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 #ifndef _SYS_TIME_H
#define _SYS_TIME_H #define _SYS_TIME_H
#define _INCLUDE_TIMESPEC_MACROS
#include <bits/attrs.h> #include <bits/attrs.h>
#include <bits/timespec.h> #include <bits/timespec.h>