c57cc482cdad9111161da19f2e533e6a9a6d1d12
[olsrd.git] / src / scheduler.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: scheduler.c,v 1.17 2004/11/12 21:20:23 kattemat Exp $
23  *
24  */
25
26
27 #include "defs.h"
28 #include "scheduler.h"
29 #include "tc_set.h"
30 #include "link_set.h"
31 #include "duplicate_set.h"
32 #include "mpr_selector_set.h"
33 #include "mid_set.h"
34 #include "mpr.h"
35 #include "olsr.h"
36 #include "build_msg.h"
37
38
39 static float pollrate;
40
41
42
43 /**
44  *Main scheduler event loop. Polls at every
45  *sched_poll_interval and calls all functions
46  *that are timed out or that are triggered.
47  *Also calls the olsr_process_changes()
48  *function at every poll.
49  *
50  *
51  *@return nada
52  */
53
54 void
55 scheduler()
56 {
57   struct timespec remainder_spec;
58   struct timespec sleeptime_spec;
59
60   /*
61    *Used to calculate sleep time
62    */
63   struct timeval start_of_loop;
64   struct timeval end_of_loop;
65   struct timeval time_used;
66   struct timeval interval;
67   struct timeval sleeptime_val;
68
69   olsr_u32_t interval_usec;
70
71   struct event_entry *entry;
72   struct timeout_entry *time_out_entry;
73
74   struct interface *ifn;
75  
76   pollrate = olsr_cnf->pollrate;
77
78   interval_usec = (olsr_u32_t)(pollrate * 1000000);
79
80   interval.tv_sec = interval_usec / 1000000;
81   interval.tv_usec = interval_usec % 1000000;
82
83   olsr_printf(1, "Scheduler started - polling every %0.2f seconds\n", pollrate);
84
85   olsr_printf(3, "Max jitter is %f\n\n", max_jitter);
86
87
88
89   /* Main scheduler event loop */
90
91   for(;;)
92     {
93
94       gettimeofday(&start_of_loop, NULL);
95
96       /* Update the global timestamp */
97       gettimeofday(&now, NULL);
98       nowtm = gmtime((time_t *)&now.tv_sec);
99
100       while (nowtm == NULL)
101         {
102           nowtm = gmtime((time_t *)&now.tv_sec);
103         }
104
105
106       /* Run timout functions (before packet generation) */
107
108       time_out_entry = timeout_functions;
109       
110       while(time_out_entry)
111         {
112           time_out_entry->function();
113           time_out_entry = time_out_entry->next;
114         }
115
116       /* Update */
117       
118       olsr_process_changes();
119
120
121       /* Check for changes in topology */
122
123       if(changes)
124         {
125           olsr_printf(3, "ANSN UPDATED %d\n\n", ansn);
126           ansn++;
127 #warning changes is set to OLSR_FALSE in scheduler now
128           changes = OLSR_FALSE;
129         }
130
131
132       /* Check scheduled events */
133
134       entry = event_functions;
135
136       /* UPDATED - resets timer upon triggered execution */
137       while(entry)
138         {
139           entry->since_last += pollrate;
140
141           /* Timed out */
142           if((entry->since_last > entry->interval) ||
143              /* Triggered */
144              ((entry->trigger != NULL) &&
145               (*(entry->trigger) == 1)))
146             {
147               /* Run scheduled function */
148               entry->function(entry->param);
149
150               /* Set jitter */
151               entry->since_last = (float) random()/RAND_MAX;
152               entry->since_last *= max_jitter;
153               
154               /* Reset trigger */
155               if(entry->trigger != NULL)
156                 *(entry->trigger) = 0;
157               
158               //olsr_printf(3, "Since_last jitter: %0.2f\n", entry->since_last);
159
160             }
161
162           entry = entry->next;
163         }
164
165
166
167       /* looping trough interfaces and emmittin pending data */
168       for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
169         { 
170           if(net_output_pending(ifn) && TIMED_OUT(&fwdtimer[ifn->if_nr])) 
171             net_output(ifn);
172         }
173
174
175       gettimeofday(&end_of_loop, NULL);
176
177       timersub(&end_of_loop, &start_of_loop, &time_used);
178
179
180       //printf("Time to sleep: %ld\n", sleeptime.tv_nsec);
181       //printf("Time used: %ld\n", time_used.tv_usec/1000);
182
183       if(timercmp(&time_used, &interval, <))
184         {
185           timersub(&interval, &time_used, &sleeptime_val);
186           
187           // printf("sleeptime_val = %u.%06u\n",
188           //        sleeptime_val.tv_sec, sleeptime_val.tv_usec);
189           
190           sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
191           sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * 1000;
192           
193           while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
194             sleeptime_spec = remainder_spec;
195         }
196       
197     }//end for
198 }
199
200
201 /*
202  *
203  *@param initial how long utnil the first generation
204  *@param trigger pointer to a boolean indicating that
205  *this function should be triggered immediatley
206  */
207 int
208 olsr_register_scheduler_event(void (*event_function)(void *), 
209                               void *par,
210                               float interval, 
211                               float initial, 
212                               olsr_u8_t *trigger)
213 {
214   struct event_entry *new_entry;
215
216   olsr_printf(3, "Scheduler event registered int: %0.2f\n", interval);
217
218   /* check that this entry is not added already */
219   new_entry = event_functions;
220   while(new_entry)
221     {
222       if((new_entry->function == event_function) &&
223          (new_entry->param == par) &&
224          (new_entry->trigger == trigger) &&
225          (new_entry->interval == interval))
226         {
227           fprintf(stderr, "Register scheduler event: Event alread registered!\n");
228           olsr_syslog(OLSR_LOG_ERR, "Register scheduler event: Event alread registered!\n");
229           return 0;
230         }
231       new_entry = new_entry->next;
232     }
233
234   new_entry = olsr_malloc(sizeof(struct event_entry), "add scheduler event");
235
236   new_entry->function = event_function;
237   new_entry->param = par;
238   new_entry->interval = interval;
239   new_entry->since_last = interval - initial;
240   new_entry->next = event_functions;
241   new_entry->trigger = trigger;
242
243   event_functions = new_entry;
244
245   return 1;
246 }
247
248
249
250 /*
251  *
252  *@param initial how long utnil the first generation
253  *@param trigger pointer to a boolean indicating that
254  *this function should be triggered immediatley
255  */
256 int
257 olsr_remove_scheduler_event(void (*event_function)(void *), 
258                             void *par,
259                             float interval, 
260                             float initial, 
261                             olsr_u8_t *trigger)
262 {
263   struct event_entry *entry, *prev;
264
265   prev = NULL;
266   entry = event_functions;
267
268   while(entry)
269     {
270       if((entry->function == event_function) &&
271          (entry->param == par) &&
272          (entry->trigger == trigger) &&
273          (entry->interval == interval))
274         {
275           if(entry == event_functions)
276             {
277               event_functions = entry->next;
278             }
279           else
280             {
281               prev->next = entry->next;
282             }
283           return 1;
284         }
285
286       prev = entry;
287       entry = entry->next;
288     }
289
290   return 0;
291 }
292
293
294 int
295 olsr_register_timeout_function(void (*time_out_function)(void))
296 {
297   struct timeout_entry *new_entry;
298
299   /* check that this entry is not added already */
300   new_entry = timeout_functions;
301   while(new_entry)
302     {
303       if(new_entry->function == time_out_function)
304         {
305           fprintf(stderr, "Register scheduler timeout: Event alread registered!\n");
306           olsr_syslog(OLSR_LOG_ERR, "Register scheduler timeout: Event alread registered!\n");
307           return 0;
308         }
309       new_entry = new_entry->next;
310     }
311
312   new_entry = olsr_malloc(sizeof(struct timeout_entry), "scheduler add timeout");
313
314   new_entry->function = time_out_function;
315   new_entry->next = timeout_functions;
316
317   timeout_functions = new_entry;
318
319   return 1;
320 }
321
322
323
324 int
325 olsr_remove_timeout_function(void (*time_out_function)(void))
326 {
327   struct timeout_entry *entry, *prev;
328
329   /* check that this entry is not added already */
330   entry = timeout_functions;
331   prev = NULL;
332
333   while(entry)
334     {
335       if(entry->function == time_out_function)
336         {
337           if(entry == timeout_functions)
338             {
339               timeout_functions = entry->next;
340             }
341           else
342             {
343               prev->next = entry->next;
344             }
345           free(entry);
346           return 1;
347         }
348       prev = entry;
349       entry = entry->next;
350     }
351
352   return 0;
353 }
354