blob: a01a9e5cf735e31971496519d16d39195af14a42 [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 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25#include <stdio.h>
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020026#include <stdlib.h>
Pablo Neira Ayusof1418372011-11-13 02:02:12 +010027#include <getopt.h>
Harald Welteec8b4502010-02-20 20:34:29 +010028
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020029#include <osmocom/core/talloc.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010030#include <osmocom/core/timer.h>
31#include <osmocom/core/select.h>
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020032#include <osmocom/core/linuxlist.h>
Harald Welteec8b4502010-02-20 20:34:29 +010033
Harald Weltee94ad582010-02-20 22:06:24 +010034#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010035
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020036static void main_timer_fired(void *data);
37static void secondary_timer_fired(void *data);
Harald Welteec8b4502010-02-20 20:34:29 +010038
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020039static unsigned int main_timer_step = 0;
40static struct osmo_timer_list main_timer = {
41 .cb = main_timer_fired,
42 .data = &main_timer_step,
Harald Welteec8b4502010-02-20 20:34:29 +010043};
44
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020045static LLIST_HEAD(timer_test_list);
46
47struct test_timer {
48 struct llist_head head;
49 struct osmo_timer_list timer;
50 struct timeval start;
51 struct timeval stop;
Harald Welteec8b4502010-02-20 20:34:29 +010052};
53
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020054/* number of test steps. We add fact(steps) timers in the whole test. */
55#define MAIN_TIMER_NSTEPS 16
Harald Welteec8b4502010-02-20 20:34:29 +010056
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020057/* time between two steps, in secs. */
58#define TIME_BETWEEN_STEPS 1
59
60/* timer imprecision that we accept for this test: 10 milliseconds. */
61#define TIMER_PRES_SECS 0
62#define TIMER_PRES_USECS 10000
63
Pablo Neira Ayusof1418372011-11-13 02:02:12 +010064static int timer_nsteps = MAIN_TIMER_NSTEPS;
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020065static unsigned int expired_timers = 0;
66static unsigned int total_timers = 0;
67static unsigned int too_late = 0;
68
69static void main_timer_fired(void *data)
Harald Welteec8b4502010-02-20 20:34:29 +010070{
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020071 unsigned int *step = data;
72 unsigned int add_in_this_step;
73 int i;
Harald Welteec8b4502010-02-20 20:34:29 +010074
Pablo Neira Ayusof1418372011-11-13 02:02:12 +010075 if (*step == timer_nsteps) {
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020076 printf("Main timer has finished, please, wait a bit for the "
77 "final report.\n");
78 return;
79 }
80 /* add 2^step pair of timers per step. */
81 add_in_this_step = (1 << *step);
82
83 for (i=0; i<add_in_this_step; i++) {
84 struct test_timer *v;
85
86 v = talloc_zero(NULL, struct test_timer);
87 if (v == NULL) {
88 fprintf(stderr, "timer_test: OOM!\n");
89 return;
90 }
91 gettimeofday(&v->start, NULL);
92 v->timer.cb = secondary_timer_fired;
93 v->timer.data = v;
94 unsigned int seconds = (random() % 10) + 1;
95 v->stop.tv_sec = v->start.tv_sec + seconds;
96 osmo_timer_schedule(&v->timer, seconds, 0);
97 llist_add(&v->head, &timer_test_list);
98 }
99 printf("added %d timers in step %u (expired=%u)\n",
100 add_in_this_step, *step, expired_timers);
101 total_timers += add_in_this_step;
102 osmo_timer_schedule(&main_timer, TIME_BETWEEN_STEPS, 0);
103 (*step)++;
104}
105
106static void secondary_timer_fired(void *data)
107{
108 struct test_timer *v = data, *this, *tmp;
109 struct timeval current, res, precision = { 1, 0 };
110
111 gettimeofday(&current, NULL);
112
113 timersub(&current, &v->stop, &res);
114 if (timercmp(&res, &precision, >)) {
115 printf("ERROR: timer %p has expired too late!\n", v->timer);
116 too_late++;
117 }
118
119 llist_del(&v->head);
120 talloc_free(data);
121 expired_timers++;
122 if (expired_timers == total_timers) {
123 printf("test over: added=%u expired=%u too_late=%u \n",
124 total_timers, expired_timers, too_late);
125 exit(EXIT_SUCCESS);
126 }
127
128 /* randomly (10%) deletion of timers. */
129 llist_for_each_entry_safe(this, tmp, &timer_test_list, head) {
130 if ((random() % 100) < 10) {
131 osmo_timer_del(&this->timer);
132 llist_del(&this->head);
133 talloc_free(this);
134 expired_timers++;
135 }
136 }
Harald Welteec8b4502010-02-20 20:34:29 +0100137}
138
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100139int main(int argc, char *argv[])
Harald Welteec8b4502010-02-20 20:34:29 +0100140{
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100141 int c;
142
143 while ((c = getopt_long(argc, argv, "s:", NULL, NULL)) != -1) {
144 switch(c) {
145 case 's':
146 timer_nsteps = atoi(optarg);
147 if (timer_nsteps <= 0) {
148 fprintf(stderr, "%s: steps must be > 0\n",
149 argv[0]);
150 exit(EXIT_FAILURE);
151 }
152 break;
153 default:
154 exit(EXIT_FAILURE);
155 }
156 }
157
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200158 printf("Running timer test for %u steps, accepting imprecision "
159 "of %u.%.6u seconds\n",
Pablo Neira Ayusof1418372011-11-13 02:02:12 +0100160 timer_nsteps, TIMER_PRES_SECS, TIMER_PRES_USECS);
Harald Welteec8b4502010-02-20 20:34:29 +0100161
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200162 osmo_timer_schedule(&main_timer, 1, 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100163
164#ifdef HAVE_SYS_SELECT_H
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200165 while (1) {
166 osmo_select_main(0);
167 }
Harald Welteec8b4502010-02-20 20:34:29 +0100168#else
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200169 printf("Select not supported on this platform!\n");
Harald Welteec8b4502010-02-20 20:34:29 +0100170#endif
171}