summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2020-09-06 19:52:24 -0400
committerAndreas Kling <kling@serenityos.org>2020-09-07 11:22:48 +0200
commite8131f503d5f1f2026ea067c27a37850b7831c43 (patch)
tree5f70fc93e970319b6b5d95d1d52532c78e24e449 /Kernel
parent4ac5cc24618bad9e362c60887d028225465083ea (diff)
downloadserenity-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.cpp5
-rw-r--r--Kernel/Time/TimeManagement.cpp26
-rw-r--r--Kernel/Time/TimeManagement.h6
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;
};