21b244edc7475ee264ce84db4329cbdf8c53f906
[bcm963xx.git] / userapps / opensource / atm2684 / atm / lane / events.c
1 /*
2  * Event handler
3  *
4  * $Id: events.c,v 1.1.1.1 2005/04/29 01:44:51 echo Exp $
5  *
6  */
7
8
9 /* System includes */
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <assert.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <sys/time.h>
16 #include <unistd.h>
17
18 /* Local includes */
19 #include "events.h"
20 #include "load.h"
21 #include "dump.h"
22 #include "mem.h"
23 #include "timers.h"
24 #include "connect.h"
25
26 /* Type definitions */
27 typedef struct _EventList_t {
28   const Event_t *event;
29   struct _EventList_t *next;
30   struct _EventList_t *prev;
31 } EventList_t;
32
33 typedef struct _HFList_t {
34   const char *name;
35   HandlerFunc_t h;
36   void *funcdata;
37   struct _HFList_t *next;
38 } HFList_t;
39
40 typedef struct _FDList_t {
41   int fd;
42   void *data;
43   struct _FDList_t *next;
44 } FDList_t;
45
46 /* Local function prototypes */
47 static void events_init0(void);
48 static void events_init1(void);
49 static void events_dump(void);
50 static void events_release(void);
51 static void event_get_fds(fd_set *dest);
52
53 /* Data */
54 static const char *rcsid="$Id: events.c,v 1.1.1.1 2005/04/29 01:44:51 echo Exp $";
55
56 const Unit_t events_unit = {
57   "events",
58   &events_init0,
59   &events_init1,
60   &events_dump,
61   &events_release
62 };
63
64 /*static mutex_t event_mutex;*/
65 static EventList_t *eventhead, *eventtail;
66 static HFList_t *handlers[CE_MAX + 1];
67 static FDList_t *fdlist;
68
69 /* Functions */
70
71 /* Initialize local data */
72 static void
73 events_init0(void)
74 {
75   unsigned int i;
76
77   eventhead = NULL;
78   eventtail = NULL;
79   for (i = 0; i <= CE_MAX; i++) {
80     handlers[i] = NULL;
81   }
82   fdlist = NULL;
83 }
84
85 /* Initialization for data that needs other units */
86 static void
87 events_init1(void)
88 {
89   set_var_str(&events_unit, "version", rcsid);
90   Debug_unit(&events_unit, "Initialized.");
91 }
92
93 /* Dump status, local data etc. */
94 static void
95 events_dump(void)
96 {
97   const EventList_t *tmp;
98   const HFList_t *htmp;
99   const FDList_t *ftmp;
100   unsigned int i;
101
102   for (tmp = eventhead; tmp != NULL; tmp = tmp->next) {
103     assert(tmp->event != NULL);
104     assert(tmp->event->unit != NULL);
105     assert(tmp->event->unit->name != NULL);
106     Debug_unit(&events_unit, "unit %s type %s data 0x%x", tmp->event->unit->name, dump_event_type(tmp->event->type), tmp->event->data);
107   }
108   for (i = 0; i <= CE_MAX; i++) {
109     for (htmp = handlers[i]; htmp != NULL; htmp = htmp->next) {
110       Debug_unit(&events_unit, "type %s func 0x%x name %s data 0x%x", dump_event_type(i), htmp->h, htmp->name, htmp->funcdata);
111     }
112   }
113   for (ftmp = fdlist; ftmp != NULL; ftmp = ftmp->next) {
114     Debug_unit(&events_unit, "polled fd %d", ftmp->fd);
115   }
116 }
117
118 /* Release allocated memory, close files etc. */
119 static void
120 events_release(void)
121 {
122   unsigned int i;
123   HFList_t *htmp;
124   FDList_t *ftmp;
125   EventList_t *tmp;
126
127   /* Lock list */
128   for (tmp = eventhead; tmp != NULL; ) {
129     assert(eventhead->event != NULL);
130     assert(eventhead->event->unit != NULL);
131     assert(eventhead->event->unit->name != NULL);
132     Debug_unit(&events_unit, "discarding unread event, unit %s type %s data 0x%x", eventhead->event->unit->name, dump_event_type(eventhead->event->type), eventhead->event->data);
133     tmp = eventhead->next;
134     mem_free(&events_unit, eventhead->event);
135     mem_free(&events_unit, eventhead);
136     eventhead = tmp;
137   }
138   eventtail = NULL;
139   /* Unlock list */
140   for (i = 0; i <= CE_MAX; i++) {
141     for (htmp = handlers[i]; htmp != NULL; htmp = htmp->next) {
142       handlers[i] = htmp->next;
143       mem_free(&events_unit, htmp);
144     }
145   }
146   for (ftmp = fdlist; ftmp != NULL; ftmp = ftmp->next) {
147     printf("Closing:%d\n",ftmp->fd);
148     close(ftmp->fd);
149     fdlist = ftmp->next;
150     mem_free(&events_unit, ftmp);
151   }
152 }
153
154 void
155 add_event_handler(EventType_t type, HandlerFunc_t func, const char *name, void *funcdata)
156 {
157   HFList_t *tmp;
158
159   tmp = (HFList_t *)mem_alloc(&events_unit, sizeof(HFList_t));
160   tmp->name = name;
161   tmp->h = func;
162   tmp->funcdata = funcdata;
163   assert(type <= CE_MAX);
164   tmp->next = handlers[type];
165   
166   handlers[type] = tmp;
167 }
168
169 static const char *typetable[CE_MAX + 1] = {
170   "New SVC",
171   "SVC closed",
172   "Data arrived",
173   "Timer expired",
174   "Dump",
175   "Restart",
176   "Termination"
177 };
178
179 /* Return event type as string */
180 const char *
181 dump_event_type(EventType_t type)
182 {
183   assert(type >= CE_SVC_CLOSE && type <= CE_MAX);
184   return typetable[type];
185 }
186
187 /* Get next event from queue */
188 const Event_t *
189 event_get_next(void)
190 {
191   const Event_t *event = NULL;
192   EventList_t *tmplist;
193   const FDList_t *tmp;
194   int poll_ret;
195   Timer_t *soonest;
196   fd_set to_select;
197   struct timeval *rolex;
198
199   while (eventtail == NULL && sig_hup == 0 && 
200          sig_usr1 == 0 && sig_alarm == 0 &&
201          sig_usr2 == 0) {
202     /* No events waiting, sleep on select() or poll() */
203     if (fdlist != NULL) {
204       soonest = timer_find_soonest(&events_unit);
205       if (soonest != NULL) {
206         rolex = (struct timeval *)mem_alloc(&events_unit,
207                                             sizeof(struct timeval));
208         rolex->tv_sec = soonest->alarm_time - time(NULL);
209         rolex->tv_usec = 0;
210         Debug_unit(&events_unit, "Sleeping %d s...", rolex->tv_sec);
211       }
212       else {
213         rolex = NULL;
214         Debug_unit(&events_unit, "Sleeping forever...");
215       }
216       event_get_fds(&to_select);
217       poll_ret = select(FD_SETSIZE, &to_select, NULL, NULL, rolex);
218       if (rolex)
219         mem_free(&events_unit,rolex);
220       Debug_unit(&events_unit, "Select: %d", poll_ret);
221       switch (poll_ret) {
222       case -1:
223         /* Error occurred */
224         dump_error(&events_unit, "select");
225         break;
226       case 0:
227         /* Timeout */
228         timer_ack(&events_unit, soonest);
229         event_put(&events_unit, CE_TIMER, (void*)soonest->data);
230         break;
231       default:
232         /* Data arrival / SVC creation */
233         Debug_unit(&events_unit,"fdlist:%d",fdlist);
234         for (tmp = fdlist; tmp != NULL; tmp = tmp->next) {
235           dump_printf(EL_DEBUG,"FD:%d",tmp->fd);
236           if (FD_ISSET(tmp->fd, &to_select)) {
237             Debug_unit(&events_unit, "Event on fd %d", tmp->fd);
238             conn_set_active(tmp->data, tmp->fd);
239             event_put(&events_unit, CE_DATA, tmp->data);
240           }       
241         }
242         break;
243       }
244     }
245     else {
246       Debug_unit(&events_unit, "No fds, restarting after 10 s");
247       sleep(10);
248       event_put(&events_unit, CE_RESTART, NULL);
249     }
250   }
251   if (sig_hup != 0) {
252       event_put(&events_unit, CE_RESTART, NULL);
253       sig_hup = 0;
254   }
255   if (sig_usr1 != 0) {
256       event_put(&events_unit, CE_DUMP, NULL);
257       sig_usr1 = 0;
258   }
259   if (sig_usr2 != 0) {
260       event_put(&events_unit, CE_EXIT, NULL);
261       sig_usr2 = 0;
262   }
263   if (sig_alarm != 0) {
264       event_put(&events_unit, CE_TIMER, NULL);
265       sig_alarm = 0;
266   }
267   Debug_unit(&events_unit, "get event %s", dump_event_type(eventtail->event->type));
268   /* Lock list */
269   event = eventhead->event;
270   if (eventhead->next != NULL) {
271     eventhead->next->prev = NULL;
272   }
273   else {
274     /* This was the last */
275     eventtail = NULL;
276   }
277   tmplist = eventhead;
278   eventhead = eventhead->next;
279   /* Unlock list */
280   mem_free(&events_unit, tmplist);
281   return event;
282 }
283
284 /* Add event to queue */
285 void
286 event_put(const Unit_t *unit, EventType_t type, void *data)
287 {
288   Event_t *event;
289   EventList_t *tmplist;
290
291   Debug_unit(&events_unit, "unit %s puts event %s", unit->name, dump_event_type(type));
292   event = (Event_t *)mem_alloc(&events_unit, sizeof(Event_t));
293   event->unit = unit;
294   event->type = type;
295   event->data = data;
296
297   tmplist = (EventList_t *)mem_alloc(&events_unit, sizeof(EventList_t));
298   tmplist->event = event;
299   tmplist->next = NULL;
300   /* Lock list */
301   tmplist->prev = eventtail;
302
303   if (eventtail != NULL) {
304     eventtail->next = tmplist;
305   }
306   else {
307     /* This is the first one */
308     eventhead = tmplist;
309   }
310   eventtail = tmplist;
311   /* Unlock list */
312 }
313
314 /* Call handlers until one returns nonzero */
315 int
316 dispatch_handlers(const Event_t *event)
317 {
318   int handled = 0;
319   const HFList_t *htmp;
320
321   assert(event != NULL);
322   for (htmp = handlers[event->type]; htmp != NULL; htmp = htmp->next) {
323     Debug_unit(&events_unit, "trying handler %s", htmp->name);
324     handled = (htmp->h(event, htmp->funcdata));
325     if (handled != 0) {
326       Debug_unit(&events_unit, "success.");
327       break;
328     }
329     else {
330       Debug_unit(&events_unit, "failed.");
331     }
332   }
333   return handled;
334 }
335
336 static void
337 event_get_fds(fd_set *dest)
338 {
339   FDList_t *tmp;
340
341   FD_ZERO(dest);
342
343   for(tmp = fdlist; tmp != NULL; tmp = tmp->next)
344     FD_SET(tmp->fd, dest);
345 }
346
347 void
348 event_add_fd(int fd, void *data)
349 {
350   FDList_t *tmp;
351
352   tmp = mem_alloc(&events_unit, sizeof(FDList_t));
353   tmp->fd = fd;
354   tmp->data = data;
355   tmp->next = fdlist;
356   fdlist = tmp;
357 }
358
359 void
360 event_remove_fd(int fd)
361 {
362   FDList_t *tmp, *prev = NULL;
363
364   for (tmp = fdlist; tmp != NULL; prev = tmp, tmp = tmp->next) {
365     if (tmp->fd == fd) {
366       break;
367     }
368   }
369
370   if (tmp == NULL) {
371     Debug_unit(&events_unit, "Could not find fd %d for removal", fd);
372     return;
373   }
374   else {
375     if (prev != NULL) {
376       prev->next = tmp->next;
377     }
378     else {
379       fdlist = tmp->next;
380     }
381     mem_free(&events_unit, tmp);
382   }
383 }