blob: 9c51ad94d1fa0874ca4bce00d1cff2ff93dd0ee9 [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/*
2 * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +02003 * (C) 2011 by Harald Welte <laforge@gnumonks.org>
Harald Welteec8b4502010-02-20 20:34:29 +01004 * All Rights Reserved
5 *
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +02006 * Authors: Holger Hans Peter Freyther <zecke@selfish.org>
7 * Pablo Neira Ayuso <pablo@gnumonks.org>
8 *
Harald Welteec8b4502010-02-20 20:34:29 +01009 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
Harald Welteec8b4502010-02-20 20:34:29 +010019 */
20
21#include <stdio.h>
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020022#include <stdlib.h>
Pablo Neira Ayuso72eb44c2011-11-13 17:40:09 +010023#include <signal.h>
Pablo Neira Ayusof1418372011-11-13 02:02:12 +010024#include <getopt.h>
Harald Welteb53717f2012-08-02 08:42:59 +020025#include <unistd.h>
Harald Welteec8b4502010-02-20 20:34:29 +010026
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020027#include <osmocom/core/talloc.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010028#include <osmocom/core/timer.h>
29#include <osmocom/core/select.h>
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020030#include <osmocom/core/linuxlist.h>
Harald Welteec8b4502010-02-20 20:34:29 +010031
Pau Espin Pedrol88955fb2023-01-18 18:54:00 +010032#include "config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010033
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020034static void main_timer_fired(void *data);
35static void secondary_timer_fired(void *data);
Harald Welteec8b4502010-02-20 20:34:29 +010036
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020037static unsigned int main_timer_step = 0;
Pablo Neira Ayuso44f423f2017-05-08 18:00:28 +020038static struct osmo_timer_list main_timer;
Harald Welteec8b4502010-02-20 20:34:29 +010039
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020040static LLIST_HEAD(timer_test_list);
41
42struct test_timer {
43 struct llist_head head;
44 struct osmo_timer_list timer;
45 struct timeval start;
46 struct timeval stop;
Harald Welteec8b4502010-02-20 20:34:29 +010047};
48
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020049/* number of test steps. We add fact(steps) timers in the whole test. */
Neels Hofmeyrdbc68172016-09-22 04:21:50 +020050#define MAIN_TIMER_NSTEPS 8
Harald Welteec8b4502010-02-20 20:34:29 +010051
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020052/* time between two steps, in secs. */
53#define TIME_BETWEEN_STEPS 1
54
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +020055/* how much time elapses between checks, in microsecs */
56#define TIME_BETWEEN_TIMER_CHECKS 423210
57
Pablo Neira Ayusof1418372011-11-13 02:02:12 +010058static int timer_nsteps = MAIN_TIMER_NSTEPS;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020059static unsigned int expired_timers = 0;
60static unsigned int total_timers = 0;
61static unsigned int too_late = 0;
Neels Hofmeyr9c9a0472016-09-22 04:23:34 +020062static unsigned int too_soon = 0;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020063
64static void main_timer_fired(void *data)
Harald Welteec8b4502010-02-20 20:34:29 +010065{
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020066 unsigned int *step = data;
67 unsigned int add_in_this_step;
68 int i;
Neels Hofmeyrd0858c22016-09-22 04:50:13 +020069 printf("main_timer_fired()\n");
Harald Welteec8b4502010-02-20 20:34:29 +010070
Pablo Neira Ayusof1418372011-11-13 02:02:12 +010071 if (*step == timer_nsteps) {
Neels Hofmeyr255dac12016-09-22 04:48:32 +020072 printf("Main timer has finished, please, "
73 "wait a bit for the final report.\n");
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020074 return;
75 }
76 /* add 2^step pair of timers per step. */
77 add_in_this_step = (1 << *step);
78
79 for (i=0; i<add_in_this_step; i++) {
80 struct test_timer *v;
81
82 v = talloc_zero(NULL, struct test_timer);
83 if (v == NULL) {
Neels Hofmeyr255dac12016-09-22 04:48:32 +020084 printf("timer_test: OOM!\n");
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020085 return;
86 }
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +020087 osmo_gettimeofday(&v->start, NULL);
Pablo Neira Ayuso44f423f2017-05-08 18:00:28 +020088 osmo_timer_setup(&v->timer, secondary_timer_fired, v);
Neels Hofmeyrd73c1cc2016-09-22 05:20:53 +020089 unsigned int seconds = (i & 0x7) + 1;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020090 v->stop.tv_sec = v->start.tv_sec + seconds;
Neels Hofmeyr633a0e72016-09-22 04:24:38 +020091 v->stop.tv_usec = v->start.tv_usec;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020092 osmo_timer_schedule(&v->timer, seconds, 0);
93 llist_add(&v->head, &timer_test_list);
Neels Hofmeyrd0858c22016-09-22 04:50:13 +020094 printf("scheduled timer at %d.%06d\n",
95 (int)v->stop.tv_sec, (int)v->stop.tv_usec);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020096 }
Neels Hofmeyr255dac12016-09-22 04:48:32 +020097 printf("added %d timers in step %u (expired=%u)\n",
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020098 add_in_this_step, *step, expired_timers);
99 total_timers += add_in_this_step;
100 osmo_timer_schedule(&main_timer, TIME_BETWEEN_STEPS, 0);
101 (*step)++;
102}
103
104static void secondary_timer_fired(void *data)
105{
106 struct test_timer *v = data, *this, *tmp;
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200107 struct timeval current, res;
108 struct timeval precision = { 0, TIME_BETWEEN_TIMER_CHECKS + 1};
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200109 int i, deleted;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200110
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +0200111 osmo_gettimeofday(&current, NULL);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200112
113 timersub(&current, &v->stop, &res);
114 if (timercmp(&res, &precision, >)) {
Neels Hofmeyr255dac12016-09-22 04:48:32 +0200115 printf("ERROR: timer has expired too late:"
116 " wanted %d.%06d now %d.%06d diff %d.%06d\n",
117 (int)v->stop.tv_sec, (int)v->stop.tv_usec,
118 (int)current.tv_sec, (int)current.tv_usec,
119 (int)res.tv_sec, (int)res.tv_usec);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200120 too_late++;
121 }
Neels Hofmeyr9c9a0472016-09-22 04:23:34 +0200122 else if (timercmp(&current, &v->stop, <)) {
Neels Hofmeyr255dac12016-09-22 04:48:32 +0200123 printf("ERROR: timer has expired too soon:"
124 " wanted %d.%06d now %d.%06d diff %d.%06d\n",
125 (int)v->stop.tv_sec, (int)v->stop.tv_usec,
126 (int)current.tv_sec, (int)current.tv_usec,
127 (int)res.tv_sec, (int)res.tv_usec);
Neels Hofmeyr9c9a0472016-09-22 04:23:34 +0200128 too_soon++;
129 }
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200130 else
131 printf("timer fired on time: %d.%06d (+ %d.%06d)\n",
132 (int)v->stop.tv_sec, (int)v->stop.tv_usec,
133 (int)res.tv_sec, (int)res.tv_usec);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200134
135 llist_del(&v->head);
136 talloc_free(data);
137 expired_timers++;
138 if (expired_timers == total_timers) {
Neels Hofmeyr255dac12016-09-22 04:48:32 +0200139 printf("test over: added=%u expired=%u too_soon=%u too_late=%u\n",
140 total_timers, expired_timers, too_soon, too_late);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200141 exit(EXIT_SUCCESS);
142 }
143
Neels Hofmeyrd73c1cc2016-09-22 05:20:53 +0200144 /* "random" deletion of timers. */
145 i = 0;
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200146 deleted = 0;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200147 llist_for_each_entry_safe(this, tmp, &timer_test_list, head) {
Neels Hofmeyrd73c1cc2016-09-22 05:20:53 +0200148 i ++;
149 if (!(i & 0x3)) {
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200150 osmo_timer_del(&this->timer);
151 llist_del(&this->head);
152 talloc_free(this);
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200153 deleted++;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200154 }
155 }
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200156 expired_timers += deleted;
157 printf("early deleted %d timers, %d still active\n", deleted,
158 total_timers - expired_timers);
Harald Welteec8b4502010-02-20 20:34:29 +0100159}
160
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100161int main(int argc, char *argv[])
Harald Welteec8b4502010-02-20 20:34:29 +0100162{
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100163 int c;
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200164 int steps;
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100165
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200166 osmo_gettimeofday_override = true;
Pablo Neira Ayuso72eb44c2011-11-13 17:40:09 +0100167
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100168 while ((c = getopt_long(argc, argv, "s:", NULL, NULL)) != -1) {
169 switch(c) {
170 case 's':
171 timer_nsteps = atoi(optarg);
172 if (timer_nsteps <= 0) {
173 fprintf(stderr, "%s: steps must be > 0\n",
174 argv[0]);
175 exit(EXIT_FAILURE);
176 }
177 break;
178 default:
179 exit(EXIT_FAILURE);
180 }
181 }
182
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200183 steps = ((MAIN_TIMER_NSTEPS * TIME_BETWEEN_STEPS + 20) * 1e6)
184 / TIME_BETWEEN_TIMER_CHECKS;
185
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200186 printf("Running timer test for %d iterations,"
187 " %d steps of %d msecs each\n",
188 timer_nsteps, steps, TIME_BETWEEN_TIMER_CHECKS / 1000);
Harald Welteec8b4502010-02-20 20:34:29 +0100189
Pablo Neira Ayuso44f423f2017-05-08 18:00:28 +0200190 osmo_timer_setup(&main_timer, main_timer_fired, &main_timer_step);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200191 osmo_timer_schedule(&main_timer, 1, 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100192
193#ifdef HAVE_SYS_SELECT_H
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200194 while (steps--) {
Neels Hofmeyrd0858c22016-09-22 04:50:13 +0200195 printf("%d.%06d\n", (int)osmo_gettimeofday_override_time.tv_sec,
196 (int)osmo_gettimeofday_override_time.tv_usec);
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200197 osmo_timers_prepare();
198 osmo_timers_update();
199 osmo_gettimeofday_override_add(0, TIME_BETWEEN_TIMER_CHECKS);
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200200 }
Harald Welteec8b4502010-02-20 20:34:29 +0100201#else
Neels Hofmeyr255dac12016-09-22 04:48:32 +0200202 printf("Select not supported on this platform!\n");
Harald Welteec8b4502010-02-20 20:34:29 +0100203#endif
Neels Hofmeyr7b4d7272016-09-22 04:47:04 +0200204 return 0;
Harald Welteec8b4502010-02-20 20:34:29 +0100205}