* luci/contrib/olsrd-luci: add timer fix from (http://gredler.at/hg/olsrd/rev/ace7c09...
[project/luci.git] / contrib / package / olsrd-luci / patches / 100-olsrd-timer-fix.patch
1
2 --- a/src/scheduler.c   Mon Aug 25 20:23:24 2008 +0200
3 +++ b/src/scheduler.c   Mon Aug 25 23:02:29 2008 +0200
4 @@ -63,7 +63,6 @@ clock_t now_times;                   /* current id
5  /* Hashed root of all timers */
6  struct list_node timer_wheel[TIMER_WHEEL_SLOTS];
7  clock_t timer_last_run;                       /* remember the last timeslot walk */
8 -struct list_node *timer_walk_list_node = NULL; /* used for timeslot walk */
9  
10  /* Pool of timers to avoid malloc() churn */
11  struct list_node free_timer_list;
12 @@ -317,6 +316,35 @@ olsr_init_timers(void)
13    timers_running = 0;
14  }
15  
16 +/*
17 + * olsr_get_next_list_entry
18 + *
19 + * Get the next list node in a hash bucket.
20 + * The listnode of the timer in may be subject to getting removed from
21 + * this timer bucket in olsr_change_timer() and olsr_stop_timer(), which
22 + * means that we can miss our walking context.
23 + * By caching the previous node we can figure out if the current node
24 + * has been removed from the hash bucket and compute the next node.
25 + */
26 +static struct list_node *
27 +olsr_get_next_list_entry (struct list_node **prev_node,
28 +                          struct list_node *current_node)
29 +{
30 +  if ((*prev_node)->next == current_node) {
31 +
32 +    /*
33 +     * No change in the list, normal traversal, update the previous node.
34 +     */
35 +    *prev_node = current_node;
36 +    return (current_node->next);
37 +  } else {
38 +
39 +    /*
40 +     * List change. Recompute the walking context.
41 +     */
42 +    return ((*prev_node)->next);
43 +  }
44 +}
45  
46  /**
47   * Walk through the timer list and check if any timer is ready to fire.
48 @@ -326,7 +354,7 @@ olsr_walk_timers(clock_t * last_run)
49  olsr_walk_timers(clock_t * last_run)
50  {
51    static struct timer_entry *timer;
52 -  struct list_node *timer_head_node;
53 +  struct list_node *timer_head_node, *timer_walk_node, *timer_walk_prev_node;
54    unsigned int timers_walked, timers_fired;
55    unsigned int total_timers_walked, total_timers_fired;
56    unsigned int wheel_slot_walks = 0;
57 @@ -347,12 +375,15 @@ olsr_walk_timers(clock_t * last_run)
58  
59      /* Get the hash slot for this clocktick */
60      timer_head_node = &timer_wheel[*last_run & TIMER_WHEEL_MASK];
61 +    timer_walk_prev_node = timer_head_node;
62  
63      /* Walk all entries hanging off this hash bucket */
64 -    for (timer_walk_list_node = timer_head_node->next; timer_walk_list_node != timer_head_node;        /* circular list */
65 -        timer_walk_list_node = timer_walk_list_node->next) {
66 -
67 -      timer = list2timer(timer_walk_list_node);
68 +    for (timer_walk_node = timer_head_node->next;
69 +         timer_walk_node != timer_head_node; /* circular list */
70 +        timer_walk_node = olsr_get_next_list_entry(&timer_walk_prev_node,
71 +                                                    timer_walk_node)) {
72 +
73 +      timer = list2timer(timer_walk_node);
74  
75        timers_walked++;
76  
77 @@ -403,11 +434,6 @@ olsr_walk_timers(clock_t * last_run)
78      /* Increment the time slot and wheel slot walk iteration */
79      (*last_run)++;
80      wheel_slot_walks++;
81 -
82 -    /*
83 -     * Mark the timer walk context unused.
84 -     */
85 -    timer_walk_list_node = NULL;
86    }
87  
88  #ifdef DEBUG
89 @@ -581,21 +607,6 @@ olsr_start_timer(unsigned int rel_time, 
90    return timer;
91  }
92  
93 -/*
94 - * Check if there is a timer walk in progress and advance the
95 - * walking context if so. Keep in mind we are about to delete
96 - * the timer from a list and this will destroy the walking context.
97 - */
98 -
99 -static inline void
100 -olsr_update_timer_walk_ctx(struct timer_entry *timer)
101 -{
102 -  if (timer_walk_list_node == &timer->timer_list) {
103 -    timer_walk_list_node = timer_walk_list_node->next;
104 -  }
105 -}
106 -
107 -
108  /**
109   * Delete a timer.
110   *
111 @@ -615,8 +626,6 @@ olsr_stop_timer(struct timer_entry *time
112               olsr_cookie_name(timer->timer_cookie),
113               timer, timer->timer_cb_context);
114  #endif
115 -
116 -  olsr_update_timer_walk_ctx(timer);
117  
118    /*
119     * Carve out of the existing wheel_slot and return to the pool
120 @@ -658,8 +667,6 @@ olsr_change_timer(struct timer_entry *ti
121    timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
122    timer->timer_jitter_pct = jitter_pct;
123  
124 -  olsr_update_timer_walk_ctx(timer);
125 -
126    /*
127     * Changes are easy: Remove timer from the exisiting timer_wheel slot
128     * and reinsert into the new slot.
129
130
131
132