Root/package/broadcom-wl/patches/100-timer_fix.patch

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

Archive Download this file



interactive