glib-aux: rework nm_utils_timespec_to_{n,u,m}sec() helpers

- add nm_utils_timespec_to_usec().
- add range checking, taken from systemd's timespec_load_nsec().
- add a unit test.
This commit is contained in:
Thomas Haller 2022-10-13 10:46:12 +02:00
parent bc74116cde
commit 41fdbd8831
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
2 changed files with 57 additions and 3 deletions

View file

@ -8,17 +8,38 @@
#include <time.h>
_nm_always_inline static inline gint64
_nm_utils_timespec_to_xsec(const struct timespec *ts, gint64 xsec_per_sec)
{
nm_assert(ts);
if (ts->tv_sec < 0 || ts->tv_nsec < 0)
return G_MAXINT64;
if (ts->tv_sec > ((guint64) G_MAXINT64) || ts->tv_nsec > ((guint64) G_MAXINT64)
|| ts->tv_sec >= (G_MAXINT64 - ((gint64) ts->tv_nsec)) / xsec_per_sec)
return G_MAXINT64;
return (((gint64) ts->tv_sec) * xsec_per_sec)
+ (((gint64) ts->tv_nsec) / (NM_UTILS_NSEC_PER_SEC / xsec_per_sec));
}
static inline gint64
nm_utils_timespec_to_nsec(const struct timespec *ts)
{
return (((gint64) ts->tv_sec) * ((gint64) NM_UTILS_NSEC_PER_SEC)) + ((gint64) ts->tv_nsec);
return _nm_utils_timespec_to_xsec(ts, NM_UTILS_NSEC_PER_SEC);
}
static inline gint64
nm_utils_timespec_to_usec(const struct timespec *ts)
{
return _nm_utils_timespec_to_xsec(ts, NM_UTILS_USEC_PER_SEC);
}
static inline gint64
nm_utils_timespec_to_msec(const struct timespec *ts)
{
return (((gint64) ts->tv_sec) * ((gint64) 1000))
+ (((gint64) ts->tv_nsec) / ((gint64) NM_UTILS_NSEC_PER_SEC / 1000));
return _nm_utils_timespec_to_xsec(ts, NM_UTILS_MSEC_PER_SEC);
}
gint64 nm_utils_get_monotonic_timestamp_nsec(void);

View file

@ -90,6 +90,38 @@ test_monotonic_timestamp(void)
/*****************************************************************************/
static void
test_timespect_to(void)
{
struct timespec ts;
int i;
for (i = 0; i < 1000; i++) {
gint64 t_msec;
gint64 t_usec;
gint64 t_nsec;
nmtst_rand_buf(NULL, &ts, sizeof(ts));
ts.tv_sec = llabs(ts.tv_sec % 100000);
ts.tv_nsec = llabs(ts.tv_nsec % NM_UTILS_NSEC_PER_SEC);
t_msec = nm_utils_timespec_to_msec(&ts);
t_usec = nm_utils_timespec_to_usec(&ts);
t_nsec = nm_utils_timespec_to_nsec(&ts);
g_assert_cmpint(t_msec, <=, t_usec / 1000);
g_assert_cmpint(t_msec + 1, >=, t_usec / 1000);
g_assert_cmpint(t_msec, <=, t_nsec / 1000000);
g_assert_cmpint(t_msec + 1, >=, t_nsec / 1000000);
g_assert_cmpint(t_usec, <=, t_nsec / 1000);
g_assert_cmpint(t_usec + 1, >=, t_nsec / 1000);
}
}
/*****************************************************************************/
static void
test_nmhash(void)
{
@ -2344,6 +2376,7 @@ main(int argc, char **argv)
g_test_add_func("/general/test_nm_static_assert", test_nm_static_assert);
g_test_add_func("/general/test_gpid", test_gpid);
g_test_add_func("/general/test_monotonic_timestamp", test_monotonic_timestamp);
g_test_add_func("/general/test_timespect_to", test_timespect_to);
g_test_add_func("/general/test_nmhash", test_nmhash);
g_test_add_func("/general/test_nm_make_strv", test_make_strv);
g_test_add_func("/general/test_nm_strdup_int", test_nm_strdup_int);