diff options
| author | Pau Espin Pedrol <pespin@sysmocom.de> | 2018-02-26 19:42:22 +0100 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2018-03-01 12:33:02 +0000 | 
| commit | 87fade88bd8471d0459a306255403e854122120e (patch) | |
| tree | 1f090b3419983d8d08c72bfd67895f7fec679dd3 /src | |
| parent | 721aa6ded9c736e3cc5b20824dd58b1af4f4a907 (diff) | |
timer: Introduce osmo_clock_gettime to override clock_gettime
Change-Id: I5bebc6e01fc9d238065bc2517058f0ba85620349
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 3 | ||||
| -rw-r--r-- | src/timer_clockgettime.c | 138 | ||||
| -rw-r--r-- | src/timer_gettimeofday.c | 2 | 
3 files changed, 141 insertions, 2 deletions
| diff --git a/src/Makefile.am b/src/Makefile.am index 3d6e6f79..2641a975 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,8 @@ endif  lib_LTLIBRARIES = libosmocore.la  libosmocore_la_LIBADD = $(BACKTRACE_LIB) $(TALLOC_LIBS) -libosmocore_la_SOURCES = timer.c timer_gettimeofday.c select.c signal.c msgb.c bits.c \ +libosmocore_la_SOURCES = timer.c timer_gettimeofday.c timer_clockgettime.c \ +			 select.c signal.c msgb.c bits.c \  			 bitvec.c bitcomp.c counter.c fsm.c \  			 write_queue.c utils.c socket.c \  			 logging.c logging_syslog.c logging_gsmtap.c rate_ctr.c \ diff --git a/src/timer_clockgettime.c b/src/timer_clockgettime.c new file mode 100644 index 00000000..8d9760c5 --- /dev/null +++ b/src/timer_clockgettime.c @@ -0,0 +1,138 @@ +/* + * (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Authors: Pau Espin Pedrol <pespin@sysmocom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/*! \addtogroup timer + *  @{ + * \file timer_clockgettime.c + * Overriding Time: osmo_clock_gettime() + *      - Useful to write and reproduce tests that depend on specific time + *        factors. This API allows to fake the timespec provided by `clock_gettime()` + *        by using a small shim osmo_clock_gettime(). + *      - Choose the clock you want to override, for instance CLOCK_MONOTONIC. + *      - If the clock override is disabled (default) for a given clock, + *        osmo_clock_gettime() will do the same as regular `clock_gettime()`. + *      - If you want osmo_clock_gettime() to provide a specific time, you must + *        enable time override with osmo_clock_override_enable(), + *        then set a pointer to the timespec storing the fake time for that + *        specific clock (`struct timespec *ts = + *        osmo_clock_override_gettimespec()`) and set it as + *        desired. Next time osmo_clock_gettime() is called, it will return the + *        values previously set through the ts pointer. + *      - A helper osmo_clock_override_add() is provided to increment a given + *        overriden clock with a specific amount of time. + */ + +/*! \file timer_clockgettime.c + */ + +#include <stdlib.h> +#include <stdbool.h> +#include <sys/time.h> +#include <time.h> + +#include <osmocom/core/timer_compat.h> + +/*! An internal structure to handle overriden time for each clock type. */ +struct fakeclock { +	bool override; +	struct timespec time; +}; + +static struct fakeclock realtime; +static struct fakeclock realtime_coarse; +static struct fakeclock mono; +static struct fakeclock mono_coarse; +static struct fakeclock mono_raw; +static struct fakeclock boottime; +static struct fakeclock boottime; +static struct fakeclock proc_cputime_id; +static struct fakeclock th_cputime_id; + +static struct fakeclock* clkid_to_fakeclock(clockid_t clk_id) +{ +	switch(clk_id) { +	case CLOCK_REALTIME: +		return &realtime; +	case CLOCK_REALTIME_COARSE: +		return &realtime_coarse; +	case CLOCK_MONOTONIC: +		return &mono; +	case CLOCK_MONOTONIC_COARSE: +		return &mono_coarse; +	case CLOCK_MONOTONIC_RAW: +		return &mono_raw; +	case CLOCK_BOOTTIME: +		return &boottime; +	case CLOCK_PROCESS_CPUTIME_ID: +		return &proc_cputime_id; +	case CLOCK_THREAD_CPUTIME_ID: +		return &th_cputime_id; +	default: +		return NULL; +	} +} + +/*! Shim around clock_gettime to be able to set the time manually. + * + * To override, use osmo_clock_override_enable and set the desired + * current time with osmo_clock_gettimespec. */ +int osmo_clock_gettime(clockid_t clk_id, struct timespec *tp) +{ +	struct fakeclock* c = clkid_to_fakeclock(clk_id); +	if (!c || !c->override) +		return clock_gettime(clk_id, tp); + +	*tp = c->time; +	return 0; +} + +/*! Convenience function to enable or disable a specific clock fake time. + */ +void osmo_clock_override_enable(clockid_t clk_id, bool enable) +{ +	struct fakeclock* c = clkid_to_fakeclock(clk_id); +	if (c) +		c->override = enable; +} + +/*! Convenience function to return a pointer to the timespec handling the + * fake time for clock clk_id. */ +struct timespec *osmo_clock_override_gettimespec(clockid_t clk_id) +{ +	struct fakeclock* c = clkid_to_fakeclock(clk_id); +	if (c) +		return &c->time; +	return NULL; +} + +/*! Convenience function to advance the fake time. + * + * Adds the given values to the clock time. */ +void osmo_clock_override_add(clockid_t clk_id, time_t secs, long nsecs) +{ +	struct timespec val = { secs, nsecs }; +	struct fakeclock* c = clkid_to_fakeclock(clk_id); +	if (c) +		timespecadd(&c->time, &val, &c->time); +} + +/*! @} */ diff --git a/src/timer_gettimeofday.c b/src/timer_gettimeofday.c index 15b5e31d..5273a3b8 100644 --- a/src/timer_gettimeofday.c +++ b/src/timer_gettimeofday.c @@ -39,7 +39,7 @@ struct timeval osmo_gettimeofday_override_time = { 23, 424242 };   * N. B: gettimeofday() is affected by discontinuous jumps in the system time   *       (e.g., if the system administrator manually changes the system time).   *       Hence this should NEVER be used for elapsed time computation. - *       Instead, clock_gettime(CLOCK_MONOTONIC, ..) should be used for that (with similar shim if necessary). + *       Instead, osmo_clock_gettime() with CLOCK_MONOTONIC should be used for that.   */  int osmo_gettimeofday(struct timeval *tv, struct timezone *tz)  { | 
