Loading...
Searching...
No Matches
Osmocom timers

Timer management: More...

## Files

file | timer.h
| Osmocom timer handling routines.
file | timer_compat.h
| Compatibility header with some helpers.
file | timer.c
file | timer_clockgettime.c
| Overriding Time: osmo_clock_gettime()
file | timer_gettimeofday.c
| Overriding Time: osmo_gettimeofday()

## Data Structures

struct | osmo_timer_list
| A structure representing a single instance of a timer. More...

## Macros

#define | OSMO_SEC2MIN(sec) ((sec % (60 * 60)) / 60)
#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 | timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define | timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
#define | timercmp(a, b, CMP)
#define | timeradd(a, b, result)
#define | timersub(a, b, result)
#define | timespecisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec)
#define | timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
#define | timespeccmp(a, b, CMP)
#define | timespecadd(a, b, result)
#define | timespecsub(a, b, result)

## Functions

void | osmo_timer_setup (struct osmo_timer_list *timer, void(*cb)(void *data), void *data)
| set up timer callback and data
void | osmo_timer_add (struct osmo_timer_list *timer)
| add a new timer to the timer management
void | osmo_timer_schedule (struct osmo_timer_list *timer, int seconds, int microseconds)
| schedule a timer at a given future relative time
void | osmo_timer_del (struct osmo_timer_list *timer)
| delete a timer from timer management
int | osmo_timer_pending (const struct osmo_timer_list *timer)
| check if given timer is still pending
int | osmo_timer_remaining (const struct osmo_timer_list *timer, const struct timeval *now, struct timeval *remaining)
| compute the remaining time of a timer
struct timeval * | osmo_timers_nearest (void)
| Determine time between now and the nearest timer.
int | osmo_timers_nearest_ms (void)
| Determine time between now and the nearest timer in milliseconds.
void | osmo_timers_prepare (void)
| Find the nearest time and update nearest_p.
int | osmo_timers_update (void)
| fire all timers... and remove them
int | osmo_timers_check (void)
| Check how many timers we have in the system.
int | osmo_gettimeofday (struct timeval *tv, struct timezone *tz)
| shim around gettimeofday to be able to set the time manually.
int | osmo_clock_gettime (clockid_t clk_id, struct timespec *tp)
void | osmo_gettimeofday_override_add (time_t secs, suseconds_t usecs)
| convenience function to advance the fake time.
void | osmo_clock_override_enable (clockid_t clk_id, bool enable)
void | osmo_clock_override_add (clockid_t clk_id, time_t secs, long nsecs)
struct timespec * | osmo_clock_override_gettimespec (clockid_t clk_id)
static void | __add_timer (struct osmo_timer_list *timer)
static void | update_nearest (struct timeval *cand, struct timeval *current)

## Variables

bool | osmo_gettimeofday_override
struct timeval | osmo_gettimeofday_override_time
static __thread struct timeval | nearest
static __thread struct timeval * | nearest_p
static __thread struct rb_root | timer_root = RB_ROOT
bool | osmo_gettimeofday_override = false
struct timeval | osmo_gettimeofday_override_time = { 23, 424242 }

## Detailed Description

Timer management:

Osmocom timer abstraction; modelled after linux kernel timers.

- Create a struct osmo_timer_list
- Fill out timeout and use osmo_timer_add(), or use osmo_timer_schedule() to schedule a timer in x seconds and microseconds from now...
- Use osmo_timer_del() to remove the timer

Internally:

- We hook into select.c to give a timeval of the nearest timer. On already passed timers we give it a 0 to immediately fire after the select
- osmo_timers_update() will call the callbacks and remove the timers.

## Macro Definition Documentation

## OSMO_SEC2DAY

#define OSMO_SEC2DAY | ( |  | sec | ) | ((sec % (60 * 60 * 24 * 365)) / (60 * 60 * 24)) /* we ignore leap year for simplicity */

## OSMO_SEC2HRS

#define OSMO_SEC2HRS | ( |  | sec | ) | ((sec % (60 * 60 * 24)) / (60 * 60))

## OSMO_SEC2MIN

#define OSMO_SEC2MIN | ( |  | sec | ) | ((sec % (60 * 60)) / 60)

## timeradd

#define timeradd | ( |  | a,
|  |  | b,
|  |  | result
| ) |  |

Value:
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
if ((result)->tv_usec >= 1000000) \
{ \
++(result)->tv_sec; \
(result)->tv_usec -= 1000000; \
} \
} while (0)
subsys
char subsys[16]
logging sub-system
Definition gsmtap.h:9

## timerclear

#define timerclear | ( |  | tvp | ) | ((tvp)->tv_sec = (tvp)->tv_usec = 0)

## timercmp

#define timercmp | ( |  | a,
|  |  | b,
|  |  | CMP
| ) |  |

Value:
(((a)->tv_sec == (b)->tv_sec) ? \
((a)->tv_usec CMP (b)->tv_usec) : \
((a)->tv_sec CMP (b)->tv_sec))

## timerisset

#define timerisset | ( |  | tvp | ) | ((tvp)->tv_sec || (tvp)->tv_usec)

## timersub

#define timersub | ( |  | a,
|  |  | b,
|  |  | result
| ) |  |

Value:
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)

## timespecadd

#define timespecadd | ( |  | a,
|  |  | b,
|  |  | result
| ) |  |

Value:
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_nsec = (a)->tv_nsec + (b)->tv_nsec; \
if ((result)->tv_nsec >= 1000000000) \
{ \
++(result)->tv_sec; \
(result)->tv_nsec -= 1000000000; \
} \
} while (0)

## timespecclear

#define timespecclear | ( |  | tvp | ) | ((tvp)->tv_sec = (tvp)->tv_nsec = 0)

## timespeccmp

#define timespeccmp | ( |  | a,
|  |  | b,
|  |  | CMP
| ) |  |

Value:
(((a)->tv_sec == (b)->tv_sec) ? \
((a)->tv_nsec CMP (b)->tv_nsec) : \
((a)->tv_sec CMP (b)->tv_sec))

## timespecisset

#define timespecisset | ( |  | tvp | ) | ((tvp)->tv_sec || (tvp)->tv_nsec)

## timespecsub

#define timespecsub | ( |  | a,
|  |  | b,
|  |  | result
| ) |  |

Value:
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
if ((result)->tv_nsec < 0) { \
--(result)->tv_sec; \
(result)->tv_nsec += 1000000000; \
} \
} while (0)

## Function Documentation

## __add_timer()

static void __add_timer | ( | struct osmo_timer_list * | timer | ) |

static

References container_of, osmo_timer_list::node, rb_insert_color(), rb_link_node(), rb_root::rb_node, subsys, osmo_timer_list::timeout, timer_root, and timercmp.

Referenced by osmo_timer_add().

## osmo_clock_gettime()

int osmo_clock_gettime | ( | clockid_t | clk_id,
|  | struct timespec * | tp
| ) |  |

## osmo_clock_override_add()

void osmo_clock_override_add | ( | clockid_t | clk_id,
|  | time_t | secs,
|  | long | nsecs
| ) |  |

## osmo_clock_override_enable()

void osmo_clock_override_enable | ( | clockid_t | clk_id,
|  | bool | enable
| ) |  |

## osmo_clock_override_gettimespec()

struct timespec * osmo_clock_override_gettimespec | ( | clockid_t | clk_id | ) |

## osmo_gettimeofday()

int osmo_gettimeofday | ( | struct timeval * | tv,
|  | struct timezone * | tz
| ) |  |

shim around gettimeofday to be able to set the time manually.

To override, set osmo_gettimeofday_override == true and set the desired current time in osmo_gettimeofday_override_time.

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, osmo_clock_gettime() with CLOCK_MONOTONIC should be used for that.

References osmo_gettimeofday_override, osmo_gettimeofday_override_time, and subsys.

Referenced by _gsmtap_raw_output(), _output_buf(), osmo_timer_remaining(), osmo_timer_schedule(), osmo_timers_prepare(), and osmo_timers_update().

## osmo_gettimeofday_override_add()

void osmo_gettimeofday_override_add | ( | time_t | secs,
|  | suseconds_t | usecs
| ) |  |

convenience function to advance the fake time.

Add the given values to osmo_gettimeofday_override_time.

References osmo_gettimeofday_override_time, subsys, and timeradd.

## osmo_timer_add()

void osmo_timer_add | ( | struct osmo_timer_list * | timer | ) |

add a new timer to the timer management

Parameters

  [in] | timer | the timer that should be added

References __add_timer(), osmo_timer_list::active, INIT_LLIST_HEAD, osmo_timer_list::list, and osmo_timer_del().

Referenced by osmo_timer_schedule().

## osmo_timer_del()

void osmo_timer_del | ( | struct osmo_timer_list * | timer | ) |

delete a timer from timer management

Parameters

  [in] | timer | the to-be-deleted timer

This function can be used to delete a previously added/scheduled timer from the timer management code.

References osmo_timer_list::active, osmo_timer_list::list, llist_del_init(), llist_empty(), osmo_timer_list::node, rb_erase(), and timer_root.

Referenced by osmo_fsm_inst_free(), osmo_soft_uart_flush_rx(), osmo_soft_uart_free(), osmo_timer_add(), osmo_timers_update(), and state_chg().

## osmo_timer_pending()

int osmo_timer_pending | ( | const struct osmo_timer_list * | timer | ) |

check if given timer is still pending

Parameters

  [in] | timer | the to-be-checked timer

Returns
  1 if pending, 0 otherwise

This function can be used to determine whether a given timer has alredy expired (returns 0) or is still pending (returns 1)

References osmo_timer_list::active.

Referenced by state_chg().

## osmo_timer_remaining()

int osmo_timer_remaining | ( | const struct osmo_timer_list * | timer,
|  | const struct timeval * | now,
|  | struct timeval * | remaining
| ) |  |

compute the remaining time of a timer

Parameters

  [in] | timer | the to-be-checked timer
  [in] | now | the current time (NULL if not known)
  [out] | remaining | remaining time until timer fires

Returns
  0 if timer has not expired yet, -1 if it has

This function can be used to determine the amount of time remaining until the expiration of the timer.

References osmo_gettimeofday(), subsys, osmo_timer_list::timeout, and timersub.

Referenced by state_chg().

## osmo_timer_schedule()

void osmo_timer_schedule | ( | struct osmo_timer_list * | timer,
|  | int | seconds,
|  | int | microseconds
| ) |  |

schedule a timer at a given future relative time

Parameters

  [in] | timer | the to-be-added timer
  [in] | seconds | number of seconds from now
  [in] | microseconds | number of microseconds from now

This function can be used to (re-)schedule a given timer at a specified number of seconds+microseconds in the future. It will internally add it to the timer management data structures, thus osmo_timer_add() is automatically called.

References osmo_gettimeofday(), osmo_timer_add(), subsys, osmo_timer_list::timeout, and timeradd.

Referenced by osmo_stats_tcp_set_interval(), state_chg(), stats_tcp_poll_timer_cb(), and suart_rx_ch().

## osmo_timer_setup()

void osmo_timer_setup | ( | struct osmo_timer_list * | timer,
|  | void(*)(void *data) | cb,
|  | void * | data
| ) |  |

set up timer callback and data

Parameters

  [in] | timer | the timer that should be added
  [in] | cb | function to be called when timer expires
  [in] | data | pointer to data that passed to the callback function

References osmo_timer_list::cb, and osmo_timer_list::data.

Referenced by __attribute__(), osmo_fsm_inst_alloc(), and osmo_soft_uart_configure().

## osmo_timers_check()

int osmo_timers_check | ( | void |  | ) |

Check how many timers we have in the system.

Returns
  number of osmo_timer_list registered

References node, rb_first(), rb_next(), subsys, and timer_root.

## osmo_timers_nearest()

struct timeval * osmo_timers_nearest | ( | void |  | ) |

Determine time between now and the nearest timer.

Returns
  pointer to timeval of nearest timer, NULL if there is none

if we have a nearest time return the delta between the current time and the time of the nearest timer. If the nearest timer timed out return NULL and then we will dispatch everything after the select

References nearest_p.

## osmo_timers_nearest_ms()

int osmo_timers_nearest_ms | ( | void |  | ) |

Determine time between now and the nearest timer in milliseconds.

Returns
  number of milliseconds until nearest timer expires; -1 if no timers pending

References nearest_p, and subsys.

## osmo_timers_prepare()

void osmo_timers_prepare | ( | void |  | ) |

Find the nearest time and update nearest_p.

References container_of, nearest_p, node, osmo_timer_list::node, osmo_gettimeofday(), rb_first(), subsys, osmo_timer_list::timeout, timer_root, and update_nearest().

## osmo_timers_update()

int osmo_timers_update | ( | void |  | ) |

fire all timers... and remove them

References osmo_timer_list::cb, container_of, osmo_timer_list::data, INIT_LLIST_HEAD, osmo_timer_list::list, llist_add(), llist_for_each_entry, node, osmo_timer_list::node, osmo_gettimeofday(), osmo_timer_del(), rb_first(), rb_next(), subsys, osmo_timer_list::timeout, timer_root, and timercmp.

## update_nearest()

static void update_nearest | ( | struct timeval * | cand,
|  | struct timeval * | current
| ) |  |

static

References nearest, nearest_p, subsys, timerclear, timercmp, and timersub.

Referenced by osmo_timers_prepare().

## Variable Documentation

## nearest

__thread struct timeval nearest

static

Referenced by update_nearest().

## nearest_p

__thread struct timeval* nearest_p

static

Referenced by osmo_timers_nearest(), osmo_timers_nearest_ms(), osmo_timers_prepare(), and update_nearest().

## osmo_gettimeofday_override [1/2]

bool osmo_gettimeofday_override

extern

Referenced by osmo_gettimeofday().

## osmo_gettimeofday_override [2/2]

bool osmo_gettimeofday_override = false

Referenced by osmo_gettimeofday().

## osmo_gettimeofday_override_time [1/2]

struct timeval osmo_gettimeofday_override_time

extern

Referenced by osmo_gettimeofday(), and osmo_gettimeofday_override_add().

## osmo_gettimeofday_override_time [2/2]

struct timeval osmo_gettimeofday_override_time = { 23, 424242 }

Referenced by osmo_gettimeofday(), and osmo_gettimeofday_override_add().

## timer_root

__thread struct rb_root timer_root = RB_ROOT

static

Referenced by __add_timer(), osmo_timer_del(), osmo_timers_check(), osmo_timers_prepare(), and osmo_timers_update().