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