kernel: Change the timer subsystem to use timespecs natively
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
d2334a67dd
commit
8bcec00a9d
@ -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(
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user