2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
4 * Timer rewrite (c) 2008, Hannes Gredler (hannes@gredler.at)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
44 #include "scheduler.h"
48 #include "duplicate_set.h"
49 #include "mpr_selector_set.h"
53 #include "build_msg.h"
55 #include "socket_parser.h"
59 /* Timer data, global. Externed in defs.h */
60 clock_t now_times; /* current idea of times(2) reported uptime */
62 /* Hashed root of all timers */
63 struct list_node timer_wheel[TIMER_WHEEL_SLOTS];
64 clock_t timer_last_run; /* remember the last timeslot walk */
65 struct list_node *timer_walk_list_node = NULL; /* used for timeslot walk */
67 /* Pool of timers to avoid malloc() churn */
68 struct list_node free_timer_list;
71 unsigned int timers_running;
75 * Sleep until the next scheduling interval.
77 * @param scheduler loop runtime in clock ticks.
81 olsr_scheduler_sleep(clock_t scheduler_runtime)
83 struct timespec remainder_spec, sleeptime_spec;
84 struct timeval sleeptime_val, time_used, next_interval;
85 olsr_u32_t next_interval_usec;
86 clock_t milliseconds_used;
88 /* Calculate next planned scheduler invocation */
89 next_interval_usec = olsr_cnf->pollrate * USEC_PER_SEC;
90 next_interval.tv_sec = next_interval_usec / USEC_PER_SEC;
91 next_interval.tv_usec = next_interval_usec % USEC_PER_SEC;
93 /* Determine used runtime */
94 milliseconds_used = scheduler_runtime * olsr_cnf->system_tick_divider;
95 time_used.tv_sec = milliseconds_used / MSEC_PER_SEC;
96 time_used.tv_usec = (milliseconds_used % MSEC_PER_SEC) * USEC_PER_MSEC;
98 if (timercmp(&time_used, &next_interval, <)) {
99 timersub(&next_interval, &time_used, &sleeptime_val);
101 sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
102 sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * NSEC_PER_USEC;
104 while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)
105 sleeptime_spec = remainder_spec;
110 * Main scheduler event loop. Polls at every
111 * sched_poll_interval and calls all functions
112 * that are timed out or that are triggered.
113 * Also calls the olsr_process_changes()
114 * function at every poll.
121 struct tms tms_buf; /* Buffer for times(2) calls. */
122 struct interface *ifn;
124 OLSR_PRINTF(1, "Scheduler started - polling every %0.2f seconds\n", olsr_cnf->pollrate);
125 OLSR_PRINTF(3, "Max jitter is %f\n\n", olsr_cnf->max_jitter);
127 /* Main scheduler loop */
131 * Update the global timestamp. We are using a non-wallclock timer here
132 * to avoid any undesired side effects if the system clock changes.
134 now_times = times(&tms_buf);
136 /* Read incoming data */
139 /* Process timers (before packet generation) */
140 olsr_walk_timers(&timer_last_run);
143 olsr_process_changes();
145 /* Check for changes in topology */
147 OLSR_PRINTF(3, "ANSN UPDATED %d\n\n", get_local_ansn());
148 increase_local_ansn();
149 link_changes = OLSR_FALSE;
152 /* looping trough interfaces and emmitting pending data */
153 for (ifn = ifnet; ifn ; ifn = ifn->int_next) {
154 if (net_output_pending(ifn) && TIMED_OUT(ifn->fwdtimer)) {
159 /* We are done, sleep until the next scheduling interval. */
160 olsr_scheduler_sleep(times(&tms_buf) - now_times);
163 /* The Ctrl-C signal handler thread asks us to exit */
164 if (olsr_win32_end_request) {
171 /* Tell the Ctrl-C signal handler thread that we have exited */
172 olsr_win32_end_flag = TRUE;
175 * The Ctrl-C signal handler thread will exit the process
176 * and hence also kill us.
179 Sleep(1000); /* milliseconds */
186 * Decrement a relative timer by a random number range.
188 * @param the relative timer expressed in units of milliseconds.
189 * @param the jitter in percent
190 * @param cached result of random() at system init.
191 * @return the absolute timer in system clock tick units
194 olsr_jitter(unsigned int rel_time, olsr_u8_t jitter_pct, unsigned int random)
196 unsigned int jitter_time, factorial;
199 * No jitter or, jitter larger than 99% does not make sense.
200 * Also protect against overflows resulting from > 25 bit timers.
202 if (jitter_pct == 0 || jitter_pct > 99 || rel_time > (1 << 24)) {
203 return GET_TIMESTAMP(rel_time);
207 * Play some tricks to avoid overflows with integer arithmetic.
209 jitter_time = (jitter_pct * rel_time) / 100;
210 factorial = random / (RAND_MAX / jitter_time);
211 jitter_time = (jitter_time * factorial) / (RAND_MAX / jitter_time);
214 OLSR_PRINTF(1, "TIMER: jitter %u%% rel_time %u%% to %u\n",
215 rel_time, jitter_pct, rel_time - jitter_time);
218 return GET_TIMESTAMP(rel_time - jitter_time);
223 * Allocate a timer_entry.
224 * Do this first by checking if something is available in the free_timer_pool
225 * If not then allocate a big chunk of memory and thread its elements up
226 * to the free_timer_list.
228 static struct timer_entry *
232 struct timer_entry *timer;
233 struct list_node *timer_list_node;
234 unsigned int timer_index;
237 * If there is at least one timer in the pool then remove the first
238 * element from the pool and recycle it.
240 if (!list_is_empty(&free_timer_list)) {
241 timer_list_node = free_timer_list.next;
243 /* carve it out of the pool, do not memset overwrite timer->timer_random */
244 list_remove(timer_list_node);
245 timer = list2timer(timer_list_node);
251 * Nothing in the pool, allocate a new chunk.
253 timer_block = olsr_malloc(sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK,
255 memset(timer_block, 0, sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK);
258 OLSR_PRINTF(1, "TIMER: alloc %u bytes chunk at %p\n",
259 sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK,
264 * Slice the chunk up and put the future timer_entries in the free timer pool.
267 for (timer_index = 0; timer_index < OLSR_TIMER_MEMORY_CHUNK; timer_index++) {
269 /* Insert new timers at the tail of the free_timer list */
270 list_add_before(&free_timer_list, &timer->timer_list);
273 * For performance reasons (read: frequent timer changes),
274 * precompute a random number once per timer and reuse later.
275 * The random number only gets recomputed if a periodical timer fires,
276 * such that a different jitter is applied for future firing.
278 timer->timer_random = random();
284 * There are now timers in the pool, recurse once.
286 return olsr_get_timer();
291 * Init datastructures for maintaining timers.
294 olsr_init_timers(void)
296 struct list_node *timer_head_node;
299 OLSR_PRINTF(5, "TIMER: init timers\n");
301 memset(timer_wheel, 0 , sizeof(timer_wheel));
303 timer_head_node = timer_wheel;
304 for (index = 0; index < TIMER_WHEEL_SLOTS; index++) {
305 list_head_init(timer_head_node);
310 * Reset the last timer run.
312 timer_last_run = now_times;
314 /* Timer memory pooling */
315 list_head_init(&free_timer_list);
321 * Walk through the timer list and check if any timer is ready to fire.
322 * Callback the provided function with the context pointer.
325 olsr_walk_timers(clock_t *last_run)
327 static struct timer_entry *timer;
328 struct list_node *timer_head_node;
329 unsigned int timers_walked, timers_fired;
330 unsigned int total_timers_walked, total_timers_fired;
331 unsigned int wheel_slot_walks = 0;
334 * Check the required wheel slots since the last time a timer walk was invoked,
335 * or check *all* the wheel slots, whatever is less work.
336 * The latter is meant as a safety belt if the scheduler falls behind.
338 total_timers_walked = total_timers_fired = timers_walked = timers_fired = 0;
339 while ((*last_run <= now_times) && (wheel_slot_walks < TIMER_WHEEL_SLOTS)) {
341 /* keep some statistics */
342 total_timers_walked += timers_walked;
343 total_timers_fired += timers_fired;
347 /* Get the hash slot for this clocktick */
348 timer_head_node = &timer_wheel[*last_run & TIMER_WHEEL_MASK];
350 /* Walk all entries hanging off this hash bucket */
351 for (timer_walk_list_node = timer_head_node->next;
352 timer_walk_list_node != timer_head_node; /* circular list */
353 timer_walk_list_node = timer_walk_list_node->next) {
355 timer = list2timer(timer_walk_list_node);
359 /* Ready to fire ? */
360 if (TIMED_OUT(timer->timer_clock)) {
362 olsr_printf(3, "TIMER: fire timer %p, ctx %p, "
363 "cookie %u at clocktick %u\n",
364 timer, timer->timer_cb_context, timer->timer_cookie,
365 (unsigned int)(*last_run));
367 /* This timer is expired, call into the provided callback function */
368 timer->timer_cb(timer->timer_cb_context);
370 if (timer->timer_period) {
373 * Don't restart the periodic timer if the callback function has
376 if (timer->timer_flags & OLSR_TIMER_RUNNING) {
378 /* For periodical timers, rehash the random number and restart */
379 timer->timer_random = random();
380 olsr_change_timer(timer, timer->timer_period,
381 timer->timer_jitter_pct,
382 OLSR_TIMER_PERIODIC);
388 * Don't stop the singleshot timer if the callback function has
391 if (timer->timer_flags & OLSR_TIMER_RUNNING) {
393 /* Singleshot timers are stopped and returned to the pool */
394 olsr_stop_timer(timer);
402 /* Increment the time slot and wheel slot walk iteration */
407 * Mark the timer walk context unused.
409 timer_walk_list_node = NULL;
413 olsr_printf(3, "TIMER: processed %4u/%u clockwheel slots, "
414 "timers walked %4u/%u, timers fired %u\n",
415 wheel_slot_walks, TIMER_WHEEL_SLOTS,
416 total_timers_walked, timers_running, total_timers_fired);
422 * Returns the difference between gmt and local time in seconds.
423 * Use gmtime() and localtime() to keep things simple.
425 * taken and slightly modified from www.tcpdump.org.
428 olsr_get_timezone(void)
430 #define OLSR_TIMEZONE_UNINITIALIZED -1
432 static int time_diff = OLSR_TIMEZONE_UNINITIALIZED;
434 struct tm *gmt, *loc;
438 if (time_diff != OLSR_TIMEZONE_UNINITIALIZED) {
447 time_diff = (loc->tm_hour - gmt->tm_hour) * 60 * 60
448 + (loc->tm_min - gmt->tm_min) * 60;
451 * If the year or julian day is different, we span 00:00 GMT
452 * and must add or subtract a day. Check the year first to
453 * avoid problems when the julian day wraps.
455 dir = loc->tm_year - gmt->tm_year;
457 dir = loc->tm_yday - gmt->tm_yday;
460 time_diff += dir * 24 * 60 * 60;
466 * Format an absolute wallclock system time string.
467 * May be called upto 4 times in a single printf() statement.
468 * Displays microsecond resolution.
470 * @return buffer to a formatted system time string.
473 olsr_wallclock_string(void)
475 static char buf[4][sizeof("00:00:00.000000")];
484 gettimeofday(&now, NULL);
486 sec = (int)now.tv_sec + olsr_get_timezone();
487 usec = (int)now.tv_usec;
489 snprintf(ret, sizeof(buf), "%02u:%02u:%02u.%06u",
490 (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60, usec);
497 * Format an relative non-wallclock system time string.
498 * May be called upto 4 times in a single printf() statement.
499 * Displays millisecond resolution.
501 * @param absolute time expressed in clockticks
502 * @return buffer to a formatted system time string.
505 olsr_clock_string(clock_t clock)
507 static char buf[4][sizeof("00:00:00.000")];
510 unsigned int sec, msec;
515 /* On most systems a clocktick is a 10ms quantity. */
516 msec = olsr_cnf->system_tick_divider * (unsigned int)(clock - now_times);
517 sec = msec / MSEC_PER_SEC;
519 snprintf(ret, sizeof(buf)/4, "%02u:%02u:%02u.%03u",
520 sec / 3600, (sec % 3600) / 60, (sec % 60), (msec % MSEC_PER_SEC));
529 * @param relative time expressed in milliseconds
530 * @param jitter expressed in percent
531 * @param timer callback function
532 * @param context for the callback function
533 * @return a pointer to the created entry
536 olsr_start_timer(unsigned int rel_time, olsr_u8_t jitter_pct,
537 olsr_bool periodical, void (*timer_cb_function)(void *),
538 void *context, olsr_cookie_t cookie)
540 struct timer_entry *timer;
542 timer = olsr_get_timer();
545 timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
546 timer->timer_cb = timer_cb_function;
547 timer->timer_cb_context = context;
548 timer->timer_jitter_pct = jitter_pct;
549 timer->timer_flags = OLSR_TIMER_RUNNING;
551 /* The cookie is used for debugging to traceback the originator */
552 timer->timer_cookie = cookie;
554 /* Singleshot or periodical timer ? */
556 timer->timer_period = rel_time;
558 timer->timer_period = 0;
562 * Now insert in the respective timer_wheel slot.
564 list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK],
569 OLSR_PRINTF(3, "TIMER: start timer %p firing in %s, ctx %p\n",
570 timer, olsr_clock_string(timer->timer_clock), context);
577 * Check if there is a timer walk in progress and advance the
578 * walking context if so. Keep in mind we are about to delete
579 * the timer from a list and this will destroy the walking context.
583 olsr_update_timer_walk_ctx(struct timer_entry *timer)
585 if (timer_walk_list_node == &timer->timer_list) {
586 timer_walk_list_node = timer_walk_list_node->next;
594 * @param the timer_entry that shall be removed
598 olsr_stop_timer(struct timer_entry *timer)
607 OLSR_PRINTF(3, "TIMER: stop timer %p firing in %s, ctx %p\n",
608 timer, olsr_clock_string(timer->timer_clock),
609 timer->timer_cb_context);
612 olsr_update_timer_walk_ctx(timer);
615 * Carve out of the existing wheel_slot and return to the pool
616 * rather than freeing for later reycling.
618 list_remove(&timer->timer_list);
619 list_add_before(&free_timer_list, &timer->timer_list);
620 timer->timer_flags &= ~OLSR_TIMER_RUNNING;
626 * Change a timer_entry.
628 * @param timer_entry to be changed.
629 * @param new relative time expressed in units of milliseconds.
630 * @param new jitter expressed in percent.
634 olsr_change_timer(struct timer_entry *timer, unsigned int rel_time,
635 olsr_u8_t jitter_pct, olsr_bool periodical)
643 /* Singleshot or periodical timer ? */
645 timer->timer_period = rel_time;
647 timer->timer_period = 0;
650 timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
651 timer->timer_jitter_pct = jitter_pct;
653 olsr_update_timer_walk_ctx(timer);
656 * Changes are easy: Remove timer from the exisiting timer_wheel slot
657 * and reinsert into the new slot.
659 list_remove(&timer->timer_list);
660 list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK],
664 OLSR_PRINTF(3, "TIMER: change timer %p, firing to %s, ctx %p\n",
666 olsr_clock_string(timer->timer_clock),
667 timer->timer_cb_context);
673 * This is the one stop shop for all sort of timer manipulation.
674 * Depending on the paseed in parameters a new timer is started,
675 * or an existing timer is started or an existing timer is
679 olsr_set_timer(struct timer_entry **timer_ptr, unsigned int rel_time,
680 olsr_u8_t jitter_pct, olsr_bool periodical,
681 void (*timer_cb_function)(void *), void *context,
682 olsr_cookie_t cookie)
687 /* No timer running, kick it. */
688 *timer_ptr = olsr_start_timer(rel_time, jitter_pct, periodical,
689 timer_cb_function, context, cookie);
694 /* No good future time provided, kill it.*/
695 olsr_stop_timer(*timer_ptr);
699 /* Time is ok and timer is running, change it !*/
700 olsr_change_timer(*timer_ptr, rel_time, jitter_pct, periodical);