General cleanups in header files
[olsrd.git] / src / scheduler.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: scheduler.c,v 1.26 2005/02/20 18:52:19 kattemat Exp $
40  */
41
42
43 #include "defs.h"
44 #include "scheduler.h"
45 #include "tc_set.h"
46 #include "link_set.h"
47 #include "duplicate_set.h"
48 #include "mpr_selector_set.h"
49 #include "mid_set.h"
50 #include "mpr.h"
51 #include "olsr.h"
52 #include "build_msg.h"
53
54
55 static float pollrate;
56
57 /* Lists */
58 static struct timeout_entry *timeout_functions;
59 static struct event_entry *event_functions;
60
61
62 /**
63  *Main scheduler event loop. Polls at every
64  *sched_poll_interval and calls all functions
65  *that are timed out or that are triggered.
66  *Also calls the olsr_process_changes()
67  *function at every poll.
68  *
69  *
70  *@return nada
71  */
72
73 void
74 scheduler()
75 {
76   struct timespec remainder_spec;
77   struct timespec sleeptime_spec;
78
79   /*
80    *Used to calculate sleep time
81    */
82   clock_t end_of_loop;
83   struct timeval time_used;
84   struct timeval interval;
85   struct timeval sleeptime_val;
86
87   olsr_u32_t interval_usec;
88
89   struct event_entry *entry;
90   struct timeout_entry *time_out_entry;
91
92   struct interface *ifn;
93
94   /* Global buffer for times(2) calls */
95   struct tms tms_buf;
96  
97   pollrate = olsr_cnf->pollrate;
98   interval_usec = (olsr_u32_t)(pollrate * 1000000);
99
100   interval.tv_sec = interval_usec / 1000000;
101   interval.tv_usec = interval_usec % 1000000;
102
103   olsr_printf(1, "Scheduler started - polling every %0.2f seconds\n", pollrate);
104   olsr_printf(3, "Max jitter is %f\n\n", max_jitter);
105
106   /* Main scheduler event loop */
107   for(;;)
108     {
109
110       /* Update now_times */
111       if((now_times = times(&tms_buf)) < 0)
112         {
113           if((now_times = times(&tms_buf)) < 0)
114             {
115               fprintf(stderr, "Fatal!scheduler could not get new_times.\n%s\n", strerror(errno));
116               olsr_syslog(OLSR_LOG_ERR, "Fatal!scheduler could not get new_times.\n%m\n");
117               olsr_exit(__func__, EXIT_FAILURE);
118             }
119         }
120
121       /* Update the global timestamp - kept for plugin compat */
122       gettimeofday(&now, NULL);
123       nowtm = gmtime((time_t *)&now.tv_sec);
124
125       while (nowtm == NULL)
126         {
127           nowtm = gmtime((time_t *)&now.tv_sec);
128         }
129
130
131       /* Run timout functions (before packet generation) */
132
133       time_out_entry = timeout_functions;
134       
135       while(time_out_entry)
136         {
137           time_out_entry->function();
138           time_out_entry = time_out_entry->next;
139         }
140
141       /* Update */
142       
143       olsr_process_changes();
144
145
146       /* Check for changes in topology */
147       if(changes)
148         {
149           olsr_printf(3, "ANSN UPDATED %d\n\n", get_local_ansn());
150           increase_local_ansn();
151           changes = OLSR_FALSE;
152         }
153
154
155       /* Check scheduled events */
156       entry = event_functions;
157
158       /* UPDATED - resets timer upon triggered execution */
159       while(entry)
160         {
161           entry->since_last += pollrate;
162
163           /* Timed out */
164           if((entry->since_last > entry->interval) ||
165              /* Triggered */
166              ((entry->trigger != NULL) &&
167               (*(entry->trigger) == 1)))
168             {
169               /* Run scheduled function */
170               entry->function(entry->param);
171
172               /* Set jitter */
173               entry->since_last = (float) random()/RAND_MAX;
174               entry->since_last *= max_jitter;
175               
176               /* Reset trigger */
177               if(entry->trigger != NULL)
178                 *(entry->trigger) = 0;
179               
180               //olsr_printf(3, "Since_last jitter: %0.2f\n", entry->since_last);
181
182             }
183
184           entry = entry->next;
185         }
186
187
188
189       /* looping trough interfaces and emmittin pending data */
190       for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
191         { 
192           if(net_output_pending(ifn) && TIMED_OUT(fwdtimer[ifn->if_nr])) 
193             net_output(ifn);
194         }
195
196
197       if((end_of_loop = times(&tms_buf)) < 0)
198         {
199           if((end_of_loop = times(&tms_buf)) < 0)
200             {
201               fprintf(stderr, "Fatal!scheduler could not get new_times.\n%s\n", strerror(errno));
202               olsr_syslog(OLSR_LOG_ERR, "Fatal!scheduler could not get new_times.\n%m\n");
203               olsr_exit(__func__, EXIT_FAILURE);
204             }
205         }
206
207       //printf("Tick diff: %d\n", end_of_loop - now_times);
208       time_used.tv_sec = ((end_of_loop - now_times) * system_tick_divider) / 1000;
209       time_used.tv_usec = ((end_of_loop - now_times) * system_tick_divider) % 1000;
210
211       //printf("Time used: %d.%04d\n", time_used.tv_sec, time_used.tv_usec);
212
213       if(timercmp(&time_used, &interval, <))
214         {
215           timersub(&interval, &time_used, &sleeptime_val);
216           
217           // printf("sleeptime_val = %u.%06u\n",
218           //        sleeptime_val.tv_sec, sleeptime_val.tv_usec);
219           
220           sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
221           sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * 1000;
222           
223           while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
224             sleeptime_spec = remainder_spec;
225         }
226       
227     }//end for
228 }
229
230
231 /*
232  *
233  *@param initial how long utnil the first generation
234  *@param trigger pointer to a boolean indicating that
235  *this function should be triggered immediatley
236  */
237 int
238 olsr_register_scheduler_event(void (*event_function)(void *), 
239                               void *par,
240                               float interval, 
241                               float initial, 
242                               olsr_u8_t *trigger)
243 {
244   struct event_entry *new_entry;
245
246   olsr_printf(3, "Scheduler event registered int: %0.2f\n", interval);
247
248   /* check that this entry is not added already */
249   new_entry = event_functions;
250   while(new_entry)
251     {
252       if((new_entry->function == event_function) &&
253          (new_entry->param == par) &&
254          (new_entry->trigger == trigger) &&
255          (new_entry->interval == interval))
256         {
257           fprintf(stderr, "Register scheduler event: Event alread registered!\n");
258           olsr_syslog(OLSR_LOG_ERR, "Register scheduler event: Event alread registered!\n");
259           return 0;
260         }
261       new_entry = new_entry->next;
262     }
263
264   new_entry = olsr_malloc(sizeof(struct event_entry), "add scheduler event");
265
266   new_entry->function = event_function;
267   new_entry->param = par;
268   new_entry->interval = interval;
269   new_entry->since_last = interval - initial;
270   new_entry->next = event_functions;
271   new_entry->trigger = trigger;
272
273   event_functions = new_entry;
274
275   return 1;
276 }
277
278
279
280 /*
281  *
282  *@param initial how long utnil the first generation
283  *@param trigger pointer to a boolean indicating that
284  *this function should be triggered immediatley
285  */
286 int
287 olsr_remove_scheduler_event(void (*event_function)(void *), 
288                             void *par,
289                             float interval, 
290                             float initial, 
291                             olsr_u8_t *trigger)
292 {
293   struct event_entry *entry, *prev;
294
295   prev = NULL;
296   entry = event_functions;
297
298   while(entry)
299     {
300       if((entry->function == event_function) &&
301          (entry->param == par) &&
302          (entry->trigger == trigger) &&
303          (entry->interval == interval))
304         {
305           if(entry == event_functions)
306             {
307               event_functions = entry->next;
308             }
309           else
310             {
311               prev->next = entry->next;
312             }
313           return 1;
314         }
315
316       prev = entry;
317       entry = entry->next;
318     }
319
320   return 0;
321 }
322
323
324 int
325 olsr_register_timeout_function(void (*time_out_function)(void))
326 {
327   struct timeout_entry *new_entry;
328
329   /* check that this entry is not added already */
330   new_entry = timeout_functions;
331   while(new_entry)
332     {
333       if(new_entry->function == time_out_function)
334         {
335           fprintf(stderr, "Register scheduler timeout: Event alread registered!\n");
336           olsr_syslog(OLSR_LOG_ERR, "Register scheduler timeout: Event alread registered!\n");
337           return 0;
338         }
339       new_entry = new_entry->next;
340     }
341
342   new_entry = olsr_malloc(sizeof(struct timeout_entry), "scheduler add timeout");
343
344   new_entry->function = time_out_function;
345   new_entry->next = timeout_functions;
346
347   timeout_functions = new_entry;
348
349   return 1;
350 }
351
352
353
354 int
355 olsr_remove_timeout_function(void (*time_out_function)(void))
356 {
357   struct timeout_entry *entry, *prev;
358
359   /* check that this entry is not added already */
360   entry = timeout_functions;
361   prev = NULL;
362
363   while(entry)
364     {
365       if(entry->function == time_out_function)
366         {
367           if(entry == timeout_functions)
368             {
369               timeout_functions = entry->next;
370             }
371           else
372             {
373               prev->next = entry->next;
374             }
375           free(entry);
376           return 1;
377         }
378       prev = entry;
379       entry = entry->next;
380     }
381
382   return 0;
383 }
384