bbfc9c2a94764f0e60d3a9af190379f1ade8fef2
[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.19 2004/11/15 15:56:07 tlopatic 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           // if the MPR selector might have been updated, we have to print
126           // the updated neighbour table, as it now contains an "MPRS" column
127
128           olsr_print_neighbor_table();
129
130           olsr_printf(3, "ANSN UPDATED %d\n\n", ansn);
131           ansn++;
132 #warning changes is set to OLSR_FALSE in scheduler now
133           changes = OLSR_FALSE;
134         }
135
136
137       /* Check scheduled events */
138
139       entry = event_functions;
140
141       /* UPDATED - resets timer upon triggered execution */
142       while(entry)
143         {
144           entry->since_last += pollrate;
145
146           /* Timed out */
147           if((entry->since_last > entry->interval) ||
148              /* Triggered */
149              ((entry->trigger != NULL) &&
150               (*(entry->trigger) == 1)))
151             {
152               /* Run scheduled function */
153               entry->function(entry->param);
154
155               /* Set jitter */
156               entry->since_last = (float) random()/RAND_MAX;
157               entry->since_last *= max_jitter;
158               
159               /* Reset trigger */
160               if(entry->trigger != NULL)
161                 *(entry->trigger) = 0;
162               
163               //olsr_printf(3, "Since_last jitter: %0.2f\n", entry->since_last);
164
165             }
166
167           entry = entry->next;
168         }
169
170
171
172       /* looping trough interfaces and emmittin pending data */
173       for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
174         { 
175           if(net_output_pending(ifn) && TIMED_OUT(&fwdtimer[ifn->if_nr])) 
176             net_output(ifn);
177         }
178
179
180       gettimeofday(&end_of_loop, NULL);
181
182       timersub(&end_of_loop, &start_of_loop, &time_used);
183
184
185       //printf("Time to sleep: %ld\n", sleeptime.tv_nsec);
186       //printf("Time used: %ld\n", time_used.tv_usec/1000);
187
188       if(timercmp(&time_used, &interval, <))
189         {
190           timersub(&interval, &time_used, &sleeptime_val);
191           
192           // printf("sleeptime_val = %u.%06u\n",
193           //        sleeptime_val.tv_sec, sleeptime_val.tv_usec);
194           
195           sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
196           sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * 1000;
197           
198           while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
199             sleeptime_spec = remainder_spec;
200         }
201       
202     }//end for
203 }
204
205
206 /*
207  *
208  *@param initial how long utnil the first generation
209  *@param trigger pointer to a boolean indicating that
210  *this function should be triggered immediatley
211  */
212 int
213 olsr_register_scheduler_event(void (*event_function)(void *), 
214                               void *par,
215                               float interval, 
216                               float initial, 
217                               olsr_u8_t *trigger)
218 {
219   struct event_entry *new_entry;
220
221   olsr_printf(3, "Scheduler event registered int: %0.2f\n", interval);
222
223   /* check that this entry is not added already */
224   new_entry = event_functions;
225   while(new_entry)
226     {
227       if((new_entry->function == event_function) &&
228          (new_entry->param == par) &&
229          (new_entry->trigger == trigger) &&
230          (new_entry->interval == interval))
231         {
232           fprintf(stderr, "Register scheduler event: Event alread registered!\n");
233           olsr_syslog(OLSR_LOG_ERR, "Register scheduler event: Event alread registered!\n");
234           return 0;
235         }
236       new_entry = new_entry->next;
237     }
238
239   new_entry = olsr_malloc(sizeof(struct event_entry), "add scheduler event");
240
241   new_entry->function = event_function;
242   new_entry->param = par;
243   new_entry->interval = interval;
244   new_entry->since_last = interval - initial;
245   new_entry->next = event_functions;
246   new_entry->trigger = trigger;
247
248   event_functions = new_entry;
249
250   return 1;
251 }
252
253
254
255 /*
256  *
257  *@param initial how long utnil the first generation
258  *@param trigger pointer to a boolean indicating that
259  *this function should be triggered immediatley
260  */
261 int
262 olsr_remove_scheduler_event(void (*event_function)(void *), 
263                             void *par,
264                             float interval, 
265                             float initial, 
266                             olsr_u8_t *trigger)
267 {
268   struct event_entry *entry, *prev;
269
270   prev = NULL;
271   entry = event_functions;
272
273   while(entry)
274     {
275       if((entry->function == event_function) &&
276          (entry->param == par) &&
277          (entry->trigger == trigger) &&
278          (entry->interval == interval))
279         {
280           if(entry == event_functions)
281             {
282               event_functions = entry->next;
283             }
284           else
285             {
286               prev->next = entry->next;
287             }
288           return 1;
289         }
290
291       prev = entry;
292       entry = entry->next;
293     }
294
295   return 0;
296 }
297
298
299 int
300 olsr_register_timeout_function(void (*time_out_function)(void))
301 {
302   struct timeout_entry *new_entry;
303
304   /* check that this entry is not added already */
305   new_entry = timeout_functions;
306   while(new_entry)
307     {
308       if(new_entry->function == time_out_function)
309         {
310           fprintf(stderr, "Register scheduler timeout: Event alread registered!\n");
311           olsr_syslog(OLSR_LOG_ERR, "Register scheduler timeout: Event alread registered!\n");
312           return 0;
313         }
314       new_entry = new_entry->next;
315     }
316
317   new_entry = olsr_malloc(sizeof(struct timeout_entry), "scheduler add timeout");
318
319   new_entry->function = time_out_function;
320   new_entry->next = timeout_functions;
321
322   timeout_functions = new_entry;
323
324   return 1;
325 }
326
327
328
329 int
330 olsr_remove_timeout_function(void (*time_out_function)(void))
331 {
332   struct timeout_entry *entry, *prev;
333
334   /* check that this entry is not added already */
335   entry = timeout_functions;
336   prev = NULL;
337
338   while(entry)
339     {
340       if(entry->function == time_out_function)
341         {
342           if(entry == timeout_functions)
343             {
344               timeout_functions = entry->next;
345             }
346           else
347             {
348               prev->next = entry->next;
349             }
350           free(entry);
351           return 1;
352         }
353       prev = entry;
354       entry = entry->next;
355     }
356
357   return 0;
358 }
359