Skip to content

Commit

Permalink
Add timespec_to_micros in time-util
Browse files Browse the repository at this point in the history
The function timespec_to_micros converts the time stored in a struct
timespec into microseconds (uint64_t type).

Signed-off-by: Joonyoung Shim <[email protected]>
  • Loading branch information
dofmind authored and engelmi committed Oct 10, 2024
1 parent 447a93e commit 08745e4
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 17 deletions.
6 changes: 3 additions & 3 deletions src/agent/agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static bool agent_check_controller_liveness(Agent *agent) {
}

now = get_time_micros_monotonic();
if (now == 0) {
if (now == USEC_INFINITY) {
bc_log_error("Failed to get the monotonic time");
return true;
}
Expand Down Expand Up @@ -2311,13 +2311,13 @@ static int agent_match_heartbeat(UNUSED sd_bus_message *m, void *userdata, UNUSE
uint64_t now_monotonic = 0;

now = get_time_micros();
if (now == 0) {
if (now == USEC_INFINITY) {
bc_log_error("Failed to get current time on heartbeat");
return 0;
}

now_monotonic = get_time_micros_monotonic();
if (now_monotonic == 0) {
if (now_monotonic == USEC_INFINITY) {
bc_log_error("Failed to get current monotonic time on heartbeat");
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions src/controller/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,13 +532,13 @@ static int node_match_heartbeat(UNUSED sd_bus_message *m, void *userdata, UNUSED
uint64_t now_monotonic = 0;

now = get_time_micros();
if (now == 0) {
if (now == USEC_INFINITY) {
bc_log_error("Failed to get current time on heartbeat");
return 0;
}

now_monotonic = get_time_micros_monotonic();
if (now_monotonic == 0) {
if (now_monotonic == USEC_INFINITY) {
bc_log_error("Failed to get current monotonic time on heartbeat");
return 0;
}
Expand Down
34 changes: 22 additions & 12 deletions src/libbluechi/common/time-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,18 @@

uint64_t get_time_micros() {
struct timespec now;
if (clock_gettime(CLOCK_REALTIME, &now) < 0) {
return 0;
}
uint64_t now_micros = now.tv_sec * sec_to_microsec_multiplier +
(uint64_t) ((double) now.tv_nsec * nanosec_to_microsec_multiplier);
return now_micros;

assert(clock_gettime(CLOCK_REALTIME, &now) == 0);

return timespec_to_micros(&now);
}

uint64_t get_time_micros_monotonic() {
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) {
return 0;
}
uint64_t now_micros = now.tv_sec * sec_to_microsec_multiplier +
(uint64_t) ((double) now.tv_nsec * nanosec_to_microsec_multiplier);
return now_micros;

assert(clock_gettime(CLOCK_MONOTONIC, &now) == 0);

return timespec_to_micros(&now);
}

uint64_t finalize_time_interval_micros(int64_t start_time_micros) {
Expand All @@ -38,6 +34,20 @@ double micros_to_millis(uint64_t time_micros) {
return (double) time_micros * microsec_to_millisec_multiplier;
}

uint64_t timespec_to_micros(const struct timespec *ts) {
assert(ts);

if (ts->tv_sec < 0 || ts->tv_nsec < 0) {
return USEC_INFINITY;
}

if ((uint64_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) {
return USEC_INFINITY;
}

return (uint64_t) ts->tv_sec * USEC_PER_SEC + (uint64_t) ts->tv_nsec / NSEC_PER_USEC;
}

char *get_formatted_log_timestamp() {
struct timespec now;
int r = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/libbluechi/common/time-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <stdbool.h>
#include <stdlib.h>

#define USEC_INFINITY UINT64_MAX

static const uint64_t sec_to_microsec_multiplier = 1000000;
static const double microsec_to_millisec_multiplier = 1e-3;
static const double nanosec_to_microsec_multiplier = 1e-3;
Expand All @@ -19,5 +21,6 @@ uint64_t get_time_micros();
uint64_t get_time_micros_monotonic();
uint64_t finalize_time_interval_micros(int64_t start_time_micros);
double micros_to_millis(uint64_t time_micros);
uint64_t timespec_to_micros(const struct timespec *ts);
char *get_formatted_log_timestamp();
char *get_formatted_log_timestamp_for_timespec(struct timespec time, bool is_gmt);
1 change: 1 addition & 0 deletions src/libbluechi/test/common/time-util/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
network_src = [
'get_log_timestamp',
'micros_to_millis_test',
'timespec_to_micros_test',
]

foreach src : network_src
Expand Down
72 changes: 72 additions & 0 deletions src/libbluechi/test/common/time-util/timespec_to_micros_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright Contributors to the Eclipse BlueChi project
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

#include <assert.h>
#include <limits.h>
#include <stdlib.h>

#include "libbluechi/common/protocol.h"
#include "libbluechi/common/time-util.h"

int main() {
struct timespec ts = { 0, 0 };

assert(timespec_to_micros(&ts) == 0);

ts.tv_sec = -1;
ts.tv_nsec = 0;
assert(timespec_to_micros(&ts) == USEC_INFINITY);

ts.tv_sec = 0;
ts.tv_nsec = -1;
assert(timespec_to_micros(&ts) == USEC_INFINITY);

ts.tv_sec = 0;
ts.tv_nsec = 1234;
assert(timespec_to_micros(&ts) == 1);

ts.tv_sec = 5678;
ts.tv_nsec = 0;
assert(timespec_to_micros(&ts) == 5678000000);

ts.tv_sec = 123;
ts.tv_nsec = 4567890;
assert(timespec_to_micros(&ts) == 123004567);

if (LONG_MAX < UINT64_MAX / USEC_PER_SEC) {
ts.tv_sec = LONG_MAX;
ts.tv_nsec = 999999999;
assert(timespec_to_micros(&ts) == (uint64_t) LONG_MAX * USEC_PER_SEC + 999999);
}

#if defined(__x86_64__) || defined(__aarch64__)
ts.tv_sec = LONG_MAX;
ts.tv_nsec = 0;
assert(timespec_to_micros(&ts) == USEC_INFINITY);

ts.tv_sec = UINT64_MAX / USEC_PER_SEC;
ts.tv_nsec = 0;
assert(timespec_to_micros(&ts) == 18446744073709000000ULL);

ts.tv_sec = UINT64_MAX / USEC_PER_SEC;
ts.tv_nsec = 551614999;
assert(timespec_to_micros(&ts) == 18446744073709551614ULL);

ts.tv_sec = UINT64_MAX / USEC_PER_SEC;
ts.tv_nsec = 551615000;
assert(timespec_to_micros(&ts) == UINT64_MAX);

ts.tv_sec = UINT64_MAX / USEC_PER_SEC;
ts.tv_nsec = 551616000;
assert(timespec_to_micros(&ts) == USEC_INFINITY);

ts.tv_sec = UINT64_MAX / USEC_PER_SEC + 1;
ts.tv_nsec = 0;
assert(timespec_to_micros(&ts) == USEC_INFINITY);
#endif

return EXIT_SUCCESS;
}

0 comments on commit 08745e4

Please sign in to comment.