100-timer_fix.patch 1.9 KB

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