fix hotplug2 event processing deadlock
[openwrt.git] / package / broadcom-wl / patches / 100-timer_fix.patch
1 Index: broadcom-wl-4.150.10.5.2/router/shared/linux_timer.c
2 ===================================================================
3 --- broadcom-wl-4.150.10.5.2.orig/router/shared/linux_timer.c   2008-04-07 00:15:24.914329846 +0200
4 +++ broadcom-wl-4.150.10.5.2/router/shared/linux_timer.c        2008-04-07 00:14:52.288470602 +0200
5 @@ -94,6 +94,7 @@
6  #define TFLAG_NONE     0
7  #define TFLAG_CANCELLED        (1<<0)
8  #define TFLAG_DELETED  (1<<1)
9 +#define TFLAG_QUEUED   (1<<2)
10  
11  struct event {
12      struct timeval it_interval;
13 @@ -207,6 +208,7 @@
14  
15         event_freelist = event->next;
16         event->next = NULL;
17 +       event->flags &= ~TFLAG_QUEUED;
18  
19         check_event_queue();
20  
21 @@ -387,6 +389,7 @@
22         }
23  
24         event->flags &= ~TFLAG_CANCELLED;
25 +       event->flags |= TFLAG_QUEUED;
26  
27         unblock_timer();
28  
29 @@ -502,7 +505,15 @@
30                 (*(event->func))((timer_t) event, (int)event->arg);
31  
32                 /* If the event has been cancelled, do NOT put it back on the queue. */
33 -               if (!(event->flags & TFLAG_CANCELLED)) {
34 +               /* Check for TFLAG_QUEUED is to avoid pathologic case, when after
35 +                * dequeueing event handler deletes its own timer and allocates new one
36 +                * which (at least in some cases) gets the same pointer and thus its
37 +                * 'flags' will be rewritten, most notably TFLAG_CANCELLED, and, to
38 +                * complete the disaster, it will be queued. alarm_handler tries to
39 +                * enqueue 'event' (which is on the same memory position as newly
40 +                * allocated timer), which results in queueing the same pointer once
41 +                * more. And this way, loop in event queue is created. */
42 +               if ( !(event->flags & TFLAG_CANCELLED) && !(event->flags & TFLAG_QUEUED) ) {
43  
44                         /* if the event is a recurring event, reset the timer and
45                          * find its correct place in the sorted list of events.
46 @@ -545,6 +556,7 @@
47                                 /* link our new event into the pending event queue. */
48                                 event->next = *ppevent;
49                                 *ppevent = event;
50 +                               event->flags |= TFLAG_QUEUED;
51                         } else {
52                                 /* there is no interval, so recycle the event structure.
53                                  * timer_delete((timer_t) event);