[PATCH] libosmocore[master]: Add function to estimate elapsed time

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.org
Wed Jan 3 14:08:56 UTC 2018


Hello 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(&current, 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>



More information about the gerrit-log mailing list