aboutsummaryrefslogtreecommitdiffstats
path: root/package/broadcom-wl-old/patches
diff options
context:
space:
mode:
Diffstat (limited to 'package/broadcom-wl-old/patches')
-rw-r--r--package/broadcom-wl-old/patches/100-timer_fix.patch51
1 files changed, 51 insertions, 0 deletions
diff --git a/package/broadcom-wl-old/patches/100-timer_fix.patch b/package/broadcom-wl-old/patches/100-timer_fix.patch
new file mode 100644
index 0000000000..d1ce9c9821
--- /dev/null
+++ b/package/broadcom-wl-old/patches/100-timer_fix.patch
@@ -0,0 +1,51 @@
+--- a/router/shared/linux_timer.c
++++ b/router/shared/linux_timer.c
+@@ -94,6 +94,7 @@ typedef long uclock_t;
+ #define TFLAG_NONE 0
+ #define TFLAG_CANCELLED (1<<0)
+ #define TFLAG_DELETED (1<<1)
++#define TFLAG_QUEUED (1<<2)
+
+ struct event {
+ struct timeval it_interval;
+@@ -207,6 +208,7 @@ int timer_create(
+
+ event_freelist = event->next;
+ event->next = NULL;
++ event->flags &= ~TFLAG_QUEUED;
+
+ check_event_queue();
+
+@@ -387,6 +389,7 @@ int timer_settime
+ }
+
+ event->flags &= ~TFLAG_CANCELLED;
++ event->flags |= TFLAG_QUEUED;
+
+ unblock_timer();
+
+@@ -502,7 +505,15 @@ static void alarm_handler(int i)
+ (*(event->func))((timer_t) event, (int)event->arg);
+
+ /* If the event has been cancelled, do NOT put it back on the queue. */
+- if (!(event->flags & TFLAG_CANCELLED)) {
++ /* Check for TFLAG_QUEUED is to avoid pathologic case, when after
++ * dequeueing event handler deletes its own timer and allocates new one
++ * which (at least in some cases) gets the same pointer and thus its
++ * 'flags' will be rewritten, most notably TFLAG_CANCELLED, and, to
++ * complete the disaster, it will be queued. alarm_handler tries to
++ * enqueue 'event' (which is on the same memory position as newly
++ * allocated timer), which results in queueing the same pointer once
++ * more. And this way, loop in event queue is created. */
++ if ( !(event->flags & TFLAG_CANCELLED) && !(event->flags & TFLAG_QUEUED) ) {
+
+ /* if the event is a recurring event, reset the timer and
+ * find its correct place in the sorted list of events.
+@@ -545,6 +556,7 @@ static void alarm_handler(int i)
+ /* link our new event into the pending event queue. */
+ event->next = *ppevent;
+ *ppevent = event;
++ event->flags |= TFLAG_QUEUED;
+ } else {
+ /* there is no interval, so recycle the event structure.
+ * timer_delete((timer_t) event);