This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Max gerrit-no-reply at lists.osmocom.orgHello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/5103
to look at the new patch set (#5).
Add function to estimate elapsed time
* add function which uses monotonic clock for proper time estimation
* add corresponding tests
Change-Id: I83d865ff633a7ebda2c943477205fd31aceda277
Related: OS#2586
---
M TODO-RELEASE
M include/osmocom/core/timer.h
M src/timer.c
M tests/timer/timer_test.c
M tests/timer/timer_test.ok
5 files changed, 168 insertions(+), 8 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/03/5103/5
diff --git a/TODO-RELEASE b/TODO-RELEASE
index a5def79..82b2e34 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -9,3 +9,4 @@
#library what description / commit summary line
core msgb_queue_free() add inline func to msgb.h
coding gsm0503_rach_ext-encode() add func to gsm0503_coding.h
+core osmo_time_elapsed() add function to estimate elapsed time
diff --git a/include/osmocom/core/timer.h b/include/osmocom/core/timer.h
index 4958efb..221709b 100644
--- a/include/osmocom/core/timer.h
+++ b/include/osmocom/core/timer.h
@@ -50,6 +50,31 @@
#define OSMO_SEC2HRS(sec) ((sec % (60 * 60 * 24)) / (60 * 60))
#define OSMO_SEC2DAY(sec) ((sec % (60 * 60 * 24 * 365)) / (60 * 60 * 24)) /* we ignore leap year for simplicity */
+#define OSMO_SEC2US(sec) (sec * 1000000)
+#define OSMO_SEC2MS(sec) (sec * 1000)
+#define OSMO_SEC2CS(sec) (sec * 100)
+
+#define OSMO_US2SEC(us) (us / 1000000)
+#define OSMO_MS2SEC(ms) (ms / 1000)
+#define OSMO_CS2SEC(cs) (cs / 100)
+
+#define OSMO_USEC2MS(us) (us / 1000)
+#define OSMO_USEC2NS(us) (us * 1000)
+
+#define OSMO_NSEC2US(ns) (ns / 1000)
+#define OSMO_NSEC2MS(ns) (ns / 1000000)
+#define OSMO_NSEC2CS(ns) (ns / 10000000)
+
+/* how much time elapses between checks, in microsecs */
+#define OSMO_TIME_TEST_MAGIC 423210
+
+enum osmo_elapsed {
+ T_SECS,
+ T_MILLIS,
+ T_CENTIS,
+ T_TEST
+};
+
/*! A structure representing a single instance of a timer */
struct osmo_timer_list {
struct rb_node node; /*!< rb-tree node header */
@@ -61,6 +86,8 @@
void *data; /*!< user data for callback */
};
+time_t osmo_time_elapsed(const struct timespec *from, enum osmo_elapsed kind);
+
/*
* timer management
*/
diff --git a/src/timer.c b/src/timer.c
index 02160a1..75307c2 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -25,6 +25,7 @@
*
*/
+#include "config.h"
/*! \addtogroup timer
* @{
@@ -35,6 +36,10 @@
#include <assert.h>
#include <string.h>
#include <limits.h>
+#include <errno.h>
+#include <time.h>
+
+#include <osmocom/core/logging.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/timer_compat.h>
#include <osmocom/core/linuxlist.h>
@@ -168,6 +173,62 @@
return 0;
}
+#if !defined(EMBEDDED)
+
+/* isolated nanoseconds clock difference */
+static inline long t_diff_nsec(const struct timespec *from, const struct timespec *to)
+{
+ return (from->tv_nsec > to->tv_nsec) ? (from->tv_nsec - to->tv_nsec) : (to->tv_nsec - from->tv_nsec);
+}
+
+/* isolated seconds clock difference */
+static inline time_t t_diff_sec(const struct timespec *from, const struct timespec *to)
+{
+ return (from->tv_sec > to->tv_sec) ? difftime(from->tv_sec, to->tv_sec) : difftime(to->tv_sec, from->tv_sec);
+}
+
+/*! Determine the time difference between now and the given time point
+ * \returns time difference
+ *
+ * \param[in] from timespec of a reference time point
+ * \param[in] kind expected return value type: milliseconds, centiseconds etc.
+ */
+time_t osmo_time_elapsed(const struct timespec *from, enum osmo_elapsed kind)
+{
+ struct timespec t_now;
+ long ns;
+ time_t sec;
+
+ if (kind == T_TEST) { /* used for internal test only: */
+ ns = 2 * from->tv_sec + OSMO_TIME_TEST_MAGIC;
+ t_now.tv_sec = OSMO_US2SEC(ns);
+ t_now.tv_nsec = OSMO_TIME_TEST_MAGIC + OSMO_USEC2NS(ns - t_now.tv_sec);
+ } else if (clock_gettime(CLOCK_MONOTONIC, &t_now) != 0) {
+ LOGP(DLGLOBAL, LOGL_ERROR, "Failed to get time for elapsed computation: %s\n", strerror(errno));
+ return 0;
+ }
+
+ ns = t_diff_nsec(&t_now, from);
+ sec = t_diff_sec(&t_now, from);
+
+ switch (kind) {
+ case T_SECS:
+ return sec;
+ case T_MILLIS:
+ return OSMO_SEC2MS(sec) + OSMO_NSEC2MS(ns);
+ case T_CENTIS:
+ return OSMO_SEC2CS(sec) + OSMO_NSEC2CS(ns);
+ case T_TEST:
+ return OSMO_SEC2US(sec) + OSMO_NSEC2US(ns);
+ default:
+ LOGP(DLGLOBAL, LOGL_ERROR, "Unhandled kind in elapsed time computation: %u\n", kind);
+ }
+
+ return 0;
+}
+
+#endif /* !EMBEDDED */
+
/*! Determine time between now and the nearest timer
* \returns pointer to timeval of nearest timer, NULL if there is none
*
diff --git a/tests/timer/timer_test.c b/tests/timer/timer_test.c
index d2b0204..03811e0 100644
--- a/tests/timer/timer_test.c
+++ b/tests/timer/timer_test.c
@@ -27,6 +27,9 @@
#include <signal.h>
#include <getopt.h>
#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>
@@ -35,7 +38,6 @@
#include "../config.h"
-static void main_timer_fired(void *data);
static void secondary_timer_fired(void *data);
static unsigned int main_timer_step = 0;
@@ -55,9 +57,6 @@
/* time between two steps, in secs. */
#define TIME_BETWEEN_STEPS 1
-
-/* how much time elapses between checks, in microsecs */
-#define TIME_BETWEEN_TIMER_CHECKS 423210
static int timer_nsteps = MAIN_TIMER_NSTEPS;
static unsigned int expired_timers = 0;
@@ -109,7 +108,7 @@
{
struct test_timer *v = data, *this, *tmp;
struct timeval current, res;
- struct timeval precision = { 0, TIME_BETWEEN_TIMER_CHECKS + 1};
+ struct timeval precision = { 0, OSMO_TIME_TEST_MAGIC + 1};
int i, deleted;
osmo_gettimeofday(¤t, NULL);
@@ -162,10 +161,35 @@
total_timers - expired_timers);
}
+static inline void print_elapsed(struct timespec *t, int step)
+{
+ time_t us, ms, cs, sec;
+
+ t->tv_sec = step;
+
+ us = osmo_time_elapsed(t, T_TEST);
+ ms = OSMO_USEC2MS(us);
+ cs = OSMO_NSEC2CS(OSMO_USEC2NS(us));
+ sec = OSMO_US2SEC(us); /* should be equal to step as long as OSMO_TIME_TEST_MAGIC < 1 second */
+
+ printf("[%d] Elapsed time: milliseconds %s, centiseconds %s => %s\n", step,
+ (OSMO_MS2SEC(ms) == sec) ? "OK" : "FAIL",
+ (OSMO_CS2SEC(cs) == sec) ? "OK" : "FAIL",
+ (step == sec) ? "OK" : "FAIL");
+}
+
int main(int argc, char *argv[])
{
int c;
int steps;
+ struct timespec t_start;
+
+ printf("Running elapsed timer tests...\n");
+
+ if (clock_gettime(CLOCK_MONOTONIC, &t_start) != 0)
+ printf("failed to start timer: %s\n", strerror(errno));
+ else
+ printf("monotonic timer started...\n");
osmo_gettimeofday_override = true;
@@ -185,11 +209,11 @@
}
steps = ((MAIN_TIMER_NSTEPS * TIME_BETWEEN_STEPS + 20) * 1e6)
- / TIME_BETWEEN_TIMER_CHECKS;
+ / OSMO_TIME_TEST_MAGIC;
printf("Running timer test for %d iterations,"
" %d steps of %d msecs each\n",
- timer_nsteps, steps, TIME_BETWEEN_TIMER_CHECKS / 1000);
+ timer_nsteps, steps, OSMO_TIME_TEST_MAGIC / 1000);
osmo_timer_setup(&main_timer, main_timer_fired, &main_timer_step);
osmo_timer_schedule(&main_timer, 1, 0);
@@ -200,10 +224,12 @@
(int)osmo_gettimeofday_override_time.tv_usec);
osmo_timers_prepare();
osmo_timers_update();
- osmo_gettimeofday_override_add(0, TIME_BETWEEN_TIMER_CHECKS);
+ osmo_gettimeofday_override_add(0, OSMO_TIME_TEST_MAGIC);
+ print_elapsed(&t_start, steps);
}
#else
printf("Select not supported on this platform!\n");
#endif
+
return 0;
}
diff --git a/tests/timer/timer_test.ok b/tests/timer/timer_test.ok
index 75b11c7..c6cae2c 100644
--- a/tests/timer/timer_test.ok
+++ b/tests/timer/timer_test.ok
@@ -1,13 +1,21 @@
+Running elapsed timer tests...
+monotonic timer started...
Running timer test for 8 iterations, 66 steps of 423 msecs each
23.424242
+[65] Elapsed time: milliseconds OK, centiseconds OK => OK
23.847452
+[64] Elapsed time: milliseconds OK, centiseconds OK => OK
24.270662
+[63] Elapsed time: milliseconds OK, centiseconds OK => OK
24.693872
main_timer_fired()
scheduled timer at 25.693872
added 1 timers in step 0 (expired=0)
+[62] Elapsed time: milliseconds OK, centiseconds OK => OK
25.117082
+[61] Elapsed time: milliseconds OK, centiseconds OK => OK
25.540292
+[60] Elapsed time: milliseconds OK, centiseconds OK => OK
25.963502
main_timer_fired()
scheduled timer at 26.963502
@@ -15,8 +23,11 @@
added 2 timers in step 1 (expired=0)
timer fired on time: 25.693872 (+ 0.269630)
early deleted 0 timers, 2 still active
+[59] Elapsed time: milliseconds OK, centiseconds OK => OK
26.386712
+[58] Elapsed time: milliseconds OK, centiseconds OK => OK
26.809922
+[57] Elapsed time: milliseconds OK, centiseconds OK => OK
27.233132
main_timer_fired()
scheduled timer at 28.233132
@@ -26,10 +37,13 @@
added 4 timers in step 2 (expired=1)
timer fired on time: 26.963502 (+ 0.269630)
early deleted 1 timers, 4 still active
+[56] Elapsed time: milliseconds OK, centiseconds OK => OK
27.656342
+[55] Elapsed time: milliseconds OK, centiseconds OK => OK
28.079552
timer fired on time: 27.963502 (+ 0.116050)
early deleted 0 timers, 3 still active
+[54] Elapsed time: milliseconds OK, centiseconds OK => OK
28.502762
main_timer_fired()
scheduled timer at 29.502762
@@ -41,10 +55,13 @@
scheduled timer at 35.502762
scheduled timer at 36.502762
added 8 timers in step 3 (expired=4)
+[53] Elapsed time: milliseconds OK, centiseconds OK => OK
28.925972
+[52] Elapsed time: milliseconds OK, centiseconds OK => OK
29.349182
timer fired on time: 29.233132 (+ 0.116050)
early deleted 2 timers, 8 still active
+[51] Elapsed time: milliseconds OK, centiseconds OK => OK
29.772392
main_timer_fired()
scheduled timer at 30.772392
@@ -64,12 +81,15 @@
scheduled timer at 36.772392
scheduled timer at 37.772392
added 16 timers in step 4 (expired=7)
+[50] Elapsed time: milliseconds OK, centiseconds OK => OK
30.195602
+[49] Elapsed time: milliseconds OK, centiseconds OK => OK
30.618812
timer fired on time: 30.502762 (+ 0.116050)
early deleted 5 timers, 18 still active
timer fired on time: 30.233132 (+ 0.385680)
early deleted 4 timers, 13 still active
+[48] Elapsed time: milliseconds OK, centiseconds OK => OK
31.042022
main_timer_fired()
scheduled timer at 32.042022
@@ -105,12 +125,15 @@
scheduled timer at 38.042022
scheduled timer at 39.042022
added 32 timers in step 5 (expired=18)
+[47] Elapsed time: milliseconds OK, centiseconds OK => OK
31.465232
timer fired on time: 31.233132 (+ 0.232100)
early deleted 11 timers, 33 still active
+[46] Elapsed time: milliseconds OK, centiseconds OK => OK
31.888442
timer fired on time: 31.772392 (+ 0.116050)
early deleted 8 timers, 24 still active
+[45] Elapsed time: milliseconds OK, centiseconds OK => OK
32.311652
main_timer_fired()
scheduled timer at 33.311652
@@ -178,12 +201,15 @@
scheduled timer at 39.311652
scheduled timer at 40.311652
added 64 timers in step 6 (expired=39)
+[44] Elapsed time: milliseconds OK, centiseconds OK => OK
32.734862
+[43] Elapsed time: milliseconds OK, centiseconds OK => OK
33.158072
timer fired on time: 33.042022 (+ 0.116050)
early deleted 21 timers, 66 still active
timer fired on time: 33.042022 (+ 0.116050)
early deleted 16 timers, 49 still active
+[42] Elapsed time: milliseconds OK, centiseconds OK => OK
33.581282
main_timer_fired()
scheduled timer at 34.581282
@@ -315,7 +341,9 @@
scheduled timer at 40.581282
scheduled timer at 41.581282
added 128 timers in step 7 (expired=78)
+[41] Elapsed time: milliseconds OK, centiseconds OK => OK
34.004492
+[40] Elapsed time: milliseconds OK, centiseconds OK => OK
34.427702
timer fired on time: 34.311652 (+ 0.116050)
early deleted 44 timers, 132 still active
@@ -323,10 +351,13 @@
early deleted 32 timers, 99 still active
timer fired on time: 34.311652 (+ 0.116050)
early deleted 24 timers, 74 still active
+[39] Elapsed time: milliseconds OK, centiseconds OK => OK
34.850912
main_timer_fired()
Main timer has finished, please, wait a bit for the final report.
+[38] Elapsed time: milliseconds OK, centiseconds OK => OK
35.274122
+[37] Elapsed time: milliseconds OK, centiseconds OK => OK
35.697332
timer fired on time: 35.581282 (+ 0.116050)
early deleted 18 timers, 55 still active
@@ -334,35 +365,49 @@
early deleted 13 timers, 41 still active
timer fired on time: 35.581282 (+ 0.116050)
early deleted 10 timers, 30 still active
+[36] Elapsed time: milliseconds OK, centiseconds OK => OK
36.120542
+[35] Elapsed time: milliseconds OK, centiseconds OK => OK
36.543752
timer fired on time: 36.311652 (+ 0.232100)
early deleted 7 timers, 22 still active
timer fired on time: 36.311652 (+ 0.232100)
early deleted 5 timers, 16 still active
+[34] Elapsed time: milliseconds OK, centiseconds OK => OK
36.966962
timer fired on time: 36.581282 (+ 0.385680)
early deleted 3 timers, 12 still active
+[33] Elapsed time: milliseconds OK, centiseconds OK => OK
37.390172
timer fired on time: 37.042022 (+ 0.348150)
early deleted 2 timers, 9 still active
+[32] Elapsed time: milliseconds OK, centiseconds OK => OK
37.813382
timer fired on time: 37.581282 (+ 0.232100)
early deleted 2 timers, 6 still active
+[31] Elapsed time: milliseconds OK, centiseconds OK => OK
38.236592
+[30] Elapsed time: milliseconds OK, centiseconds OK => OK
38.659802
+[29] Elapsed time: milliseconds OK, centiseconds OK => OK
39.083012
+[28] Elapsed time: milliseconds OK, centiseconds OK => OK
39.506222
timer fired on time: 39.311652 (+ 0.194570)
early deleted 1 timers, 4 still active
+[27] Elapsed time: milliseconds OK, centiseconds OK => OK
39.929432
timer fired on time: 39.581282 (+ 0.348150)
early deleted 0 timers, 3 still active
+[26] Elapsed time: milliseconds OK, centiseconds OK => OK
40.352642
+[25] Elapsed time: milliseconds OK, centiseconds OK => OK
40.775852
timer fired on time: 40.581282 (+ 0.194570)
early deleted 0 timers, 2 still active
+[24] Elapsed time: milliseconds OK, centiseconds OK => OK
41.199062
+[23] Elapsed time: milliseconds OK, centiseconds OK => OK
41.622272
timer fired on time: 41.581282 (+ 0.040990)
early deleted 0 timers, 1 still active
--
To view, visit https://gerrit.osmocom.org/5103
To unsubscribe, visit https://gerrit.osmocom.org/settings
Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I83d865ff633a7ebda2c943477205fd31aceda277
Gerrit-PatchSet: 5
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>