From 4e9d54e6f9a5284487b0a14a18a70395f539dd89 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 28 Oct 2023 20:55:28 +0200 Subject: [PATCH] Scheduler: switch to steady-clock Obviously the better choice and a perfect fit for our requirements; while the system-clock may jump and even move backwards on time service adjustments, the steady clock just counts the ticks since last boot. In libStdC++ both are implemented as int64_t and use nanoseconds resolution --- src/vault/real-clock.cpp | 32 ++- src/vault/real-clock.hpp | 7 +- tests/vault/gear/scheduler-service-test.cpp | 4 +- wiki/thinkPad.ichthyo.mm | 211 ++++++++++++++++++-- 4 files changed, 216 insertions(+), 38 deletions(-) diff --git a/src/vault/real-clock.cpp b/src/vault/real-clock.cpp index 24c2bb9b0..829213c87 100644 --- a/src/vault/real-clock.cpp +++ b/src/vault/real-clock.cpp @@ -22,25 +22,26 @@ /** @file real-clock.cpp - ** Implementation of simplified access to the current wall clock time. - ** - ** @todo just a rough draft as of 2012 / 2017 - ** @todo the idea was that the vault has elaborate knowledge about - ** timings and time progression; upper layers should thus be able - ** to fulfil their timing needs by querying the vault layer + ** Implementation of simplified access to current system time. + ** Actually, a _steady clock_ is employed, with an unspecified base time, + ** typically starting anew at each system boot. The micro-tick value will + ** increase monotonously, without gaps at NTP corrections, but also without + ** any relation to an external world time. */ #include "vault/real-clock.hpp" -#include +#include using lib::time::FSecs; +using std::chrono::steady_clock; +using std::chrono::microseconds; +using std::chrono::floor; namespace vault { -#define MICRO_TICS_PER_NANOSECOND (1000*1000*1000 / TimeValue::SCALE) /** events during the last ms are considered "recent" for the purpose of testing */ @@ -50,17 +51,12 @@ namespace vault { TimeValue RealClock::_readSystemTime() { - timespec now; - clock_gettime(CLOCK_REALTIME, &now); - ////////////////////////////////////////////TODO shouldn't that be CLOCK_MONOTONIC ? - ////////////////////////////////////////////TODO (what happens on ntp adjustments?) - ////////////////////////////////////////////TICKET #886 + auto now = steady_clock::now(); + auto microTicks = floor (now.time_since_epoch()) + .count(); - gavl_time_t ticksSince1970 = now.tv_sec * TimeValue::SCALE - + now.tv_nsec / MICRO_TICS_PER_NANOSECOND; - - ENSURE (ticksSince1970 == _raw(TimeValue{ticksSince1970})); - return TimeValue::buildRaw_(ticksSince1970); // bypassing the limit check + ENSURE (microTicks == _raw(TimeValue{microTicks})); + return TimeValue::buildRaw_(microTicks); // bypassing the limit check } diff --git a/src/vault/real-clock.hpp b/src/vault/real-clock.hpp index bc4325c43..e253714f1 100644 --- a/src/vault/real-clock.hpp +++ b/src/vault/real-clock.hpp @@ -26,12 +26,9 @@ ** system clock with a sufficient level of precision. The result is ** delivered in lumiera's [internal time format](\ref lib::time::Time) ** - ** @todo As of 4/23, still just a draft, but considered an established feature ** @todo this might be a good candidate also to provide some kind of ** translation service, i.e. a grid to anchor a logical time value ** with actual running wall clock time. - ** @todo not clear if this becomes some kind of central service (singleton) - ** or just a bunch of library routines ** ** @see lib/time/timevalue.hpp */ @@ -52,7 +49,7 @@ namespace vault { /** - * Convenience frontend to access the current wall clock time + * Convenience frontend to access the current raw system time */ class RealClock { @@ -63,7 +60,7 @@ namespace vault { static Time now() { - return Time(_readSystemTime()); + return Time{_readSystemTime()}; } static bool diff --git a/tests/vault/gear/scheduler-service-test.cpp b/tests/vault/gear/scheduler-service-test.cpp index 9f9bad474..40d4d8d7c 100644 --- a/tests/vault/gear/scheduler-service-test.cpp +++ b/tests/vault/gear/scheduler-service-test.cpp @@ -227,8 +227,8 @@ namespace test { pullWork(); CHECK (wasInvoked(start)); // Result: the first invocation happened immediately CHECK (slip_us < 300); - CHECK (delay_us > 900); // yet this thread was afterwards kept in sleep to await the next one - CHECK (activity::PASS == res); // instruction to re-invoke immediately + CHECK (delay_us > 900); // yet this thread was afterwards kept in sleep to await the next task; + CHECK (activity::PASS == res); // returns instruction to re-invoke immediately CHECK (not scheduler.empty()); // since there is still work in the queue start += t1ms; // (just re-adjust the reference point to calculate slip_us) diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 350022ee7..3382b4687 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -82232,9 +82232,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + - + + @@ -82312,13 +82314,35 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + + + + - + + + + + + + + + + + + + + +

+ weil beide letztlich auf den unterliegenden Systemcall gehen; die Linux-Systemclock liefert bereits Nanosekunden-Auflösung +

+ +
+
@@ -82333,8 +82357,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + @@ -86261,10 +86286,30 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - + + + + + + +
    +
  • + das Grooming-Token wird stets on-demand im Scheduler-Code erlangt +
  • +
  • + Worker rufen diesen Code über die work-Function auf +
  • +
  • + diese hat einen maximal generischen catch(...)- Handler +
  • +
+ +
+ + +
@@ -96734,8 +96779,148 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + + + + + +
+ template<
+ +

+     class Rep,
    class Period =  std::ratio<1>
+

+ class duration; +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Beispiel steady_clock +

+

+ using time_point = chrono::time_point<steady_clock, steady_clock::duration> +

+ +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +