summaryrefslogtreecommitdiff
path: root/src/basic/time-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-05-30 22:08:21 +0200
committerLennart Poettering <lennart@poettering.net>2016-06-06 19:59:07 +0200
commitfe624c4c07026fe11f37b7517e81b3814fa868bc (patch)
tree57ba86d0184d38607c644c32a7ac189d67c14ae3 /src/basic/time-util.c
parentb2bb19bbda8f5ab3ab497165bc52a0ef952348c4 (diff)
time-util: add triple timestamp object
We already have a double timestamp object that we use whenever we need both a MONOTONIC and a REALTIME timestamp taken and stored. With this change we also add a triple timestamp object that in addition stores a BOOTTIME timestamp, which is useful for a few usecases. Note that we keep dual_timestamp around, as it is useful in many cases where triple_timestamp is not, in particular because retrieving the monotonic and realtime timestamps is much cheaper on Linux that getting the boottime timestamp.
Diffstat (limited to 'src/basic/time-util.c')
-rw-r--r--src/basic/time-util.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index edd9179cb8..24e681bf85 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -87,6 +87,16 @@ dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
return ts;
}
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
+ assert(ts);
+
+ ts->realtime = now(CLOCK_REALTIME);
+ ts->monotonic = now(CLOCK_MONOTONIC);
+ ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY;
+
+ return ts;
+}
+
dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
int64_t delta;
assert(ts);
@@ -104,6 +114,24 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
return ts;
}
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
+ int64_t delta;
+
+ assert(ts);
+
+ if (u == USEC_INFINITY || u <= 0) {
+ ts->realtime = ts->monotonic = ts->boottime = u;
+ return ts;
+ }
+
+ ts->realtime = u;
+ delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
+ ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
+ ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
+
+ return ts;
+}
+
dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
int64_t delta;
assert(ts);
@@ -136,6 +164,26 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
return ts;
}
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
+
+ switch (clock) {
+
+ case CLOCK_REALTIME:
+ case CLOCK_REALTIME_ALARM:
+ return ts->realtime;
+
+ case CLOCK_MONOTONIC:
+ return ts->monotonic;
+
+ case CLOCK_BOOTTIME:
+ case CLOCK_BOOTTIME_ALARM:
+ return ts->boottime;
+
+ default:
+ return USEC_INFINITY;
+ }
+}
+
usec_t timespec_load(const struct timespec *ts) {
assert(ts);
@@ -1107,6 +1155,30 @@ clockid_t clock_boottime_or_monotonic(void) {
return CLOCK_MONOTONIC;
}
+bool clock_supported(clockid_t clock) {
+ struct timespec ts;
+
+ switch (clock) {
+
+ case CLOCK_MONOTONIC:
+ case CLOCK_REALTIME:
+ return true;
+
+ case CLOCK_BOOTTIME:
+ return clock_boottime_supported();
+
+ case CLOCK_BOOTTIME_ALARM:
+ if (!clock_boottime_supported())
+ return false;
+
+ /* fall through, after checking the cached value for CLOCK_BOOTTIME. */
+
+ default:
+ /* For everything else, check properly */
+ return clock_gettime(clock, &ts) >= 0;
+ }
+}
+
int get_timezone(char **tz) {
_cleanup_free_ char *t = NULL;
const char *e;