diff options
author | Nico Weber <thakis@chromium.org> | 2020-09-06 19:52:24 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-07 11:22:48 +0200 |
commit | e8131f503d5f1f2026ea067c27a37850b7831c43 (patch) | |
tree | 5f70fc93e970319b6b5d95d1d52532c78e24e449 /Kernel | |
parent | 4ac5cc24618bad9e362c60887d028225465083ea (diff) | |
download | serenity-e8131f503d5f1f2026ea067c27a37850b7831c43.zip |
Kernel: Let TimeManagement keep epoch time as timespec
Previously, it was kept as just a time_t and the sub-second
offset was inferred from the monotonic clock. This means that
sub-second time adjustments were ignored.
Now that `ntpquery -s` can pass in a time with sub-second
precision, it makes sense to keep time at that granularity
in the kernel.
After this, `ntpquery -s` immediately followed by `ntpquery` shows
an offset of 0.02s (that is, on the order of network roundtrip time)
instead of up to 0.75s previously.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Syscalls/clock.cpp | 5 | ||||
-rw-r--r-- | Kernel/Time/TimeManagement.cpp | 26 | ||||
-rw-r--r-- | Kernel/Time/TimeManagement.h | 6 |
3 files changed, 22 insertions, 15 deletions
diff --git a/Kernel/Syscalls/clock.cpp b/Kernel/Syscalls/clock.cpp index 1b9018173f..de83b63035 100644 --- a/Kernel/Syscalls/clock.cpp +++ b/Kernel/Syscalls/clock.cpp @@ -43,8 +43,7 @@ int Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts) ts.tv_nsec = TimeManagement::the().ticks_this_second() * 1000000; break; case CLOCK_REALTIME: - ts.tv_sec = TimeManagement::the().epoch_time(); - ts.tv_nsec = TimeManagement::the().ticks_this_second() * 1000000; + ts = TimeManagement::the().epoch_time(); break; default: return -EINVAL; @@ -67,7 +66,7 @@ int Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> us switch (clock_id) { case CLOCK_REALTIME: - TimeManagement::the().set_epoch_time(ts.tv_sec); + TimeManagement::the().set_epoch_time(ts); break; default: return -EINVAL; diff --git a/Kernel/Time/TimeManagement.cpp b/Kernel/Time/TimeManagement.cpp index 5fb1b4c52a..69b0570c22 100644 --- a/Kernel/Time/TimeManagement.cpp +++ b/Kernel/Time/TimeManagement.cpp @@ -25,6 +25,7 @@ */ #include <AK/Singleton.h> +#include <AK/Time.h> #include <Kernel/ACPI/Parser.h> #include <Kernel/CommandLine.h> #include <Kernel/Scheduler.h> @@ -52,15 +53,20 @@ bool TimeManagement::is_system_timer(const HardwareTimer& timer) const return &timer == m_system_timer.ptr(); } -void TimeManagement::set_epoch_time(time_t value) +void TimeManagement::set_epoch_time(timespec ts) { + timespec ticks = { 0, (long)ticks_this_second() * (long)1'000'000 }; + timespec_sub(ts, ticks, ts); InterruptDisabler disabler; - m_epoch_time = value; + m_epoch_time = ts; } -time_t TimeManagement::epoch_time() const +timespec TimeManagement::epoch_time() const { - return m_epoch_time; + timespec ts = m_epoch_time; + timespec ticks = { 0, (long)ticks_this_second() * (long)1'000'000 }; + timespec_add(ts, ticks, ts); + return ts; } void TimeManagement::initialize() @@ -94,14 +100,14 @@ TimeManagement::TimeManagement() if (ACPI::is_enabled()) { if (!ACPI::Parser::the()->x86_specific_flags().cmos_rtc_not_present) { RTC::initialize(); - m_epoch_time += boot_time(); + m_epoch_time.tv_sec += boot_time(); } else { klog() << "ACPI: RTC CMOS Not present"; } } else { // We just assume that we can access RTC CMOS, if ACPI isn't usable. RTC::initialize(); - m_epoch_time += boot_time(); + m_epoch_time.tv_sec += boot_time(); } if (probe_non_legacy_hardware_timers) { if (!probe_and_set_non_legacy_hardware_timers()) @@ -116,8 +122,10 @@ TimeManagement::TimeManagement() timeval TimeManagement::now_as_timeval() { - auto* time_management = s_the.ptr(); - return { time_management->epoch_time(), (suseconds_t)time_management->ticks_this_second() * (suseconds_t)1000 }; + timespec ts = s_the.ptr()->epoch_time(); + timeval tv; + timespec_to_timeval(ts, tv); + return tv; } Vector<HardwareTimer*> TimeManagement::scan_and_initialize_periodic_timers() @@ -230,7 +238,7 @@ void TimeManagement::increment_time_since_boot(const RegisterState&) if (++m_ticks_this_second >= m_time_keeper_timer->ticks_per_second()) { // FIXME: Synchronize with other clock somehow to prevent drifting apart. ++m_seconds_since_boot; - ++m_epoch_time; + ++m_epoch_time.tv_sec; m_ticks_this_second = 0; } } diff --git a/Kernel/Time/TimeManagement.h b/Kernel/Time/TimeManagement.h index 5d16060ff3..3e09c137ca 100644 --- a/Kernel/Time/TimeManagement.h +++ b/Kernel/Time/TimeManagement.h @@ -47,8 +47,8 @@ public: static void initialize(); static TimeManagement& the(); - time_t epoch_time() const; - void set_epoch_time(time_t); + timespec epoch_time() const; + void set_epoch_time(timespec); time_t seconds_since_boot() const; time_t ticks_per_second() const; time_t ticks_this_second() const; @@ -72,7 +72,7 @@ private: u32 m_ticks_this_second { 0 }; u32 m_seconds_since_boot { 0 }; - time_t m_epoch_time { 0 }; + timespec m_epoch_time { 0, 0 }; RefPtr<HardwareTimer> m_system_timer; RefPtr<HardwareTimer> m_time_keeper_timer; }; |