a12981f5ebcf3c74978bb9401fb038352766eb79
[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.22 2004/11/21 13:45:50 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
58 /**
59  *Main scheduler event loop. Polls at every
60  *sched_poll_interval and calls all functions
61  *that are timed out or that are triggered.
62  *Also calls the olsr_process_changes()
63  *function at every poll.
64  *
65  *
66  *@return nada
67  */
68
69 void
70 scheduler()
71 {
72   struct timespec remainder_spec;
73   struct timespec sleeptime_spec;
74
75   /*
76    *Used to calculate sleep time
77    */
78   struct timeval start_of_loop;
79   struct timeval end_of_loop;
80   struct timeval time_used;
81   struct timeval interval;
82   struct timeval sleeptime_val;
83
84   olsr_u32_t interval_usec;
85
86   struct event_entry *entry;
87   struct timeout_entry *time_out_entry;
88
89   struct interface *ifn;
90  
91   pollrate = olsr_cnf->pollrate;
92
93   interval_usec = (olsr_u32_t)(pollrate * 1000000);
94
95   interval.tv_sec = interval_usec / 1000000;
96   interval.tv_usec = interval_usec % 1000000;
97
98   olsr_printf(1, "Scheduler started - polling every %0.2f seconds\n", pollrate);
99
100   olsr_printf(3, "Max jitter is %f\n\n", max_jitter);
101
102
103
104   /* Main scheduler event loop */
105
106   for(;;)
107     {
108
109       gettimeofday(&start_of_loop, NULL);
110
111       /* Update the global timestamp */
112       gettimeofday(&now, NULL);
113       nowtm = gmtime((time_t *)&now.tv_sec);
114
115       while (nowtm == NULL)
116         {
117           nowtm = gmtime((time_t *)&now.tv_sec);
118         }
119
120
121       /* Run timout functions (before packet generation) */
122
123       time_out_entry = timeout_functions;
124       
125       while(time_out_entry)
126         {
127           time_out_entry->function();
128           time_out_entry = time_out_entry->next;
129         }
130
131       /* Update */
132       
133       olsr_process_changes();
134
135
136       /* Check for changes in topology */
137       if(changes)
138         {
139           olsr_printf(3, "ANSN UPDATED %d\n\n", ansn);
140           ansn++;
141 #warning changes is set to OLSR_FALSE in scheduler now
142           changes = OLSR_FALSE;
143         }
144
145
146       /* Check scheduled events */
147
148       entry = event_functions;
149
150       /* UPDATED - resets timer upon triggered execution */
151       while(entry)
152         {
153           entry->since_last += pollrate;
154
155           /* Timed out */
156           if((entry->since_last > entry->interval) ||
157              /* Triggered */
158              ((entry->trigger != NULL) &&
159               (*(entry->trigger) == 1)))
160             {
161               /* Run scheduled function */
162               entry->function(entry->param);
163
164               /* Set jitter */
165               entry->since_last = (float) random()/RAND_MAX;
166               entry->since_last *= max_jitter;
167               
168               /* Reset trigger */
169               if(entry->trigger != NULL)
170                 *(entry->trigger) = 0;
171               
172               //olsr_printf(3, "Since_last jitter: %0.2f\n", entry->since_last);
173
174             }
175
176           entry = entry->next;
177         }
178
179
180
181       /* looping trough interfaces and emmittin pending data */
182       for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
183         { 
184           if(net_output_pending(ifn) && TIMED_OUT(&fwdtimer[ifn->if_nr])) 
185             net_output(ifn);
186         }
187
188
189       gettimeofday(&end_of_loop, NULL);
190
191       timersub(&end_of_loop, &start_of_loop, &time_used);
192
193
194       //printf("Time to sleep: %ld\n", sleeptime.tv_nsec);
195       //printf("Time used: %ld\n", time_used.tv_usec/1000);
196
197       if(timercmp(&time_used, &interval, <))
198         {
199           timersub(&interval, &time_used, &sleeptime_val);
200           
201           // printf("sleeptime_val = %u.%06u\n",
202           //        sleeptime_val.tv_sec, sleeptime_val.tv_usec);
203           
204           sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
205           sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * 1000;
206           
207           while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
208             sleeptime_spec = remainder_spec;
209         }
210       
211     }//end for
212 }
213
214
215 /*
216  *
217  *@param initial how long utnil the first generation
218  *@param trigger pointer to a boolean indicating that
219  *this function should be triggered immediatley
220  */
221 int
222 olsr_register_scheduler_event(void (*event_function)(void *), 
223                               void *par,
224                               float interval, 
225                               float initial, 
226                               olsr_u8_t *trigger)
227 {
228   struct event_entry *new_entry;
229
230   olsr_printf(3, "Scheduler event registered int: %0.2f\n", interval);
231
232   /* check that this entry is not added already */
233   new_entry = event_functions;
234   while(new_entry)
235     {
236       if((new_entry->function == event_function) &&
237          (new_entry->param == par) &&
238          (new_entry->trigger == trigger) &&
239          (new_entry->interval == interval))
240         {
241           fprintf(stderr, "Register scheduler event: Event alread registered!\n");
242           olsr_syslog(OLSR_LOG_ERR, "Register scheduler event: Event alread registered!\n");
243           return 0;
244         }
245       new_entry = new_entry->next;
246     }
247
248   new_entry = olsr_malloc(sizeof(struct event_entry), "add scheduler event");
249
250   new_entry->function = event_function;
251   new_entry->param = par;
252   new_entry->interval = interval;
253   new_entry->since_last = interval - initial;
254   new_entry->next = event_functions;
255   new_entry->trigger = trigger;
256
257   event_functions = new_entry;
258
259   return 1;
260 }
261
262
263
264 /*
265  *
266  *@param initial how long utnil the first generation
267  *@param trigger pointer to a boolean indicating that
268  *this function should be triggered immediatley
269  */
270 int
271 olsr_remove_scheduler_event(void (*event_function)(void *), 
272                             void *par,
273                             float interval, 
274                             float initial, 
275                             olsr_u8_t *trigger)
276 {
277   struct event_entry *entry, *prev;
278
279   prev = NULL;
280   entry = event_functions;
281
282   while(entry)
283     {
284       if((entry->function == event_function) &&
285          (entry->param == par) &&
286          (entry->trigger == trigger) &&
287          (entry->interval == interval))
288         {
289           if(entry == event_functions)
290             {
291               event_functions = entry->next;
292             }
293           else
294             {
295               prev->next = entry->next;
296             }
297           return 1;
298         }
299
300       prev = entry;
301       entry = entry->next;
302     }
303
304   return 0;
305 }
306
307
308 int
309 olsr_register_timeout_function(void (*time_out_function)(void))
310 {
311   struct timeout_entry *new_entry;
312
313   /* check that this entry is not added already */
314   new_entry = timeout_functions;
315   while(new_entry)
316     {
317       if(new_entry->function == time_out_function)
318         {
319           fprintf(stderr, "Register scheduler timeout: Event alread registered!\n");
320           olsr_syslog(OLSR_LOG_ERR, "Register scheduler timeout: Event alread registered!\n");
321           return 0;
322         }
323       new_entry = new_entry->next;
324     }
325
326   new_entry = olsr_malloc(sizeof(struct timeout_entry), "scheduler add timeout");
327
328   new_entry->function = time_out_function;
329   new_entry->next = timeout_functions;
330
331   timeout_functions = new_entry;
332
333   return 1;
334 }
335
336
337
338 int
339 olsr_remove_timeout_function(void (*time_out_function)(void))
340 {
341   struct timeout_entry *entry, *prev;
342
343   /* check that this entry is not added already */
344   entry = timeout_functions;
345   prev = NULL;
346
347   while(entry)
348     {
349       if(entry->function == time_out_function)
350         {
351           if(entry == timeout_functions)
352             {
353               timeout_functions = entry->next;
354             }
355           else
356             {
357               prev->next = entry->next;
358             }
359           free(entry);
360           return 1;
361         }
362       prev = entry;
363       entry = entry->next;
364     }
365
366   return 0;
367 }
368