blob: bcaafdb26630e7b3ef214f82c9eabba8d49d6f30 [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>
Harald Welteec8b4502010-02-20 20:34:29 +010027
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020028#include <osmocom/core/talloc.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010029#include <osmocom/core/timer.h>
30#include <osmocom/core/select.h>
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020031#include <osmocom/core/linuxlist.h>
Harald Welteec8b4502010-02-20 20:34:29 +010032
Harald Weltee94ad582010-02-20 22:06:24 +010033#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010034
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020035static void main_timer_fired(void *data);
36static void secondary_timer_fired(void *data);
Harald Welteec8b4502010-02-20 20:34:29 +010037
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020038static unsigned int main_timer_step = 0;
39static struct osmo_timer_list main_timer = {
40 .cb = main_timer_fired,
41 .data = &main_timer_step,
Harald Welteec8b4502010-02-20 20:34:29 +010042};
43
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020044static LLIST_HEAD(timer_test_list);
45
46struct test_timer {
47 struct llist_head head;
48 struct osmo_timer_list timer;
49 struct timeval start;
50 struct timeval stop;
Harald Welteec8b4502010-02-20 20:34:29 +010051};
52
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020053/* number of test steps. We add fact(steps) timers in the whole test. */
54#define MAIN_TIMER_NSTEPS 16
Harald Welteec8b4502010-02-20 20:34:29 +010055
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020056/* time between two steps, in secs. */
57#define TIME_BETWEEN_STEPS 1
58
59/* timer imprecision that we accept for this test: 10 milliseconds. */
60#define TIMER_PRES_SECS 0
61#define TIMER_PRES_USECS 10000
62
63static unsigned int expired_timers = 0;
64static unsigned int total_timers = 0;
65static unsigned int too_late = 0;
66
67static void main_timer_fired(void *data)
Harald Welteec8b4502010-02-20 20:34:29 +010068{
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020069 unsigned int *step = data;
70 unsigned int add_in_this_step;
71 int i;
Harald Welteec8b4502010-02-20 20:34:29 +010072
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +020073 if (*step == MAIN_TIMER_NSTEPS) {
74 printf("Main timer has finished, please, wait a bit for the "
75 "final report.\n");
76 return;
77 }
78 /* add 2^step pair of timers per step. */
79 add_in_this_step = (1 << *step);
80
81 for (i=0; i<add_in_this_step; i++) {
82 struct test_timer *v;
83
84 v = talloc_zero(NULL, struct test_timer);
85 if (v == NULL) {
86 fprintf(stderr, "timer_test: OOM!\n");
87 return;
88 }
89 gettimeofday(&v->start, NULL);
90 v->timer.cb = secondary_timer_fired;
91 v->timer.data = v;
92 unsigned int seconds = (random() % 10) + 1;
93 v->stop.tv_sec = v->start.tv_sec + seconds;
94 osmo_timer_schedule(&v->timer, seconds, 0);
95 llist_add(&v->head, &timer_test_list);
96 }
97 printf("added %d timers in step %u (expired=%u)\n",
98 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;
107 struct timeval current, res, precision = { 1, 0 };
108
109 gettimeofday(&current, NULL);
110
111 timersub(&current, &v->stop, &res);
112 if (timercmp(&res, &precision, >)) {
113 printf("ERROR: timer %p has expired too late!\n", v->timer);
114 too_late++;
115 }
116
117 llist_del(&v->head);
118 talloc_free(data);
119 expired_timers++;
120 if (expired_timers == total_timers) {
121 printf("test over: added=%u expired=%u too_late=%u \n",
122 total_timers, expired_timers, too_late);
123 exit(EXIT_SUCCESS);
124 }
125
126 /* randomly (10%) deletion of timers. */
127 llist_for_each_entry_safe(this, tmp, &timer_test_list, head) {
128 if ((random() % 100) < 10) {
129 osmo_timer_del(&this->timer);
130 llist_del(&this->head);
131 talloc_free(this);
132 expired_timers++;
133 }
134 }
Harald Welteec8b4502010-02-20 20:34:29 +0100135}
136
137int main(int argc, char** argv)
138{
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200139 printf("Running timer test for %u steps, accepting imprecision "
140 "of %u.%.6u seconds\n",
141 MAIN_TIMER_NSTEPS, TIMER_PRES_SECS, TIMER_PRES_USECS);
Harald Welteec8b4502010-02-20 20:34:29 +0100142
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200143 osmo_timer_schedule(&main_timer, 1, 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100144
145#ifdef HAVE_SYS_SELECT_H
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200146 while (1) {
147 osmo_select_main(0);
148 }
Harald Welteec8b4502010-02-20 20:34:29 +0100149#else
Pablo Neira Ayuso9ebc5052011-09-26 11:46:32 +0200150 printf("Select not supported on this platform!\n");
Harald Welteec8b4502010-02-20 20:34:29 +0100151#endif
152}