[Olsr-dev] [PATCH v1 1/2] scheduler: mark timers for removal and only remove them in a cleanup walk
Ferry Huberts
(spam-protected)
Mon Feb 29 20:57:20 CET 2016
On 29/02/16 15:23, Ferry Huberts wrote:
> From: Ferry Huberts <(spam-protected)>
>
> Fixes crashes in networks with many nodes.
>
> *** olsr.org - pre-0.9.1-git_dd7c5a0-hash_b9729ef932ee0c718b5da79dcf6a5fce ***
> Build date: 2016-02-24 21:02:23 on jenkins
> http://www.olsr.org
>
> /usr/sbin/olsrd (olsr_segv_handler) src/main.c:323
> /lib/i386-linux-gnu/libc.so.6 (+0x2de78) [0xb760ce78]
> /usr/sbin/olsrd (list_remove) src/common/list.c:105
> /usr/sbin/olsrd (olsr_stop_timer) src/scheduler.c:874
> /usr/sbin/olsrd (olsr_del_nbr2_list) src/neighbor_table.c:85
> /usr/sbin/olsrd (olsr_delete_neighbor_table) src/neighbor_table.c:211
> /usr/sbin/olsrd (olsr_delete_link_entry) src/link_set.c:375
> /usr/sbin/olsrd (olsr_expire_link_entry) src/link_set.c:495
> /usr/sbin/olsrd (walk_timers) src/scheduler.c:650
> /usr/sbin/olsrd (olsr_scheduler) src/scheduler.c:506
> /usr/sbin/olsrd (main) src/main.c:705
>
> olsrd crashed, stack trace follows
> /usr/sbin/olsrd (olsr_segv_handler) src/main.c:323
> /lib/i386-linux-gnu/libc.so.6 (+0x2de78) [0xb764ce78]
> /usr/sbin/olsrd (list_remove) src/common/list.c:105
> /usr/sbin/olsrd (olsr_stop_timer) src/scheduler.c:874
> /usr/sbin/olsrd (olsr_update_gateway_entry) src/gateway.c:1208
> /usr/sbin/olsrd (olsr_input_hna) src/hna_set.c:446
> /usr/sbin/olsrd (parse_packet) src/parser.c:393
> /usr/sbin/olsrd (olsr_input) src/parser.c:496
> /usr/sbin/olsrd (poll_sockets) src/scheduler.c:341
> /usr/sbin/olsrd (olsr_scheduler) src/scheduler.c:499
> /usr/sbin/olsrd (main) src/main.c:705
>
> Signed-off-by: Ferry Huberts <(spam-protected)>
> ---
> src/scheduler.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> src/scheduler.h | 1 +
> 2 files changed, 94 insertions(+), 2 deletions(-)
>
> diff --git a/src/scheduler.c b/src/scheduler.c
> index cf8968a..062c96e 100644
> --- a/src/scheduler.c
> +++ b/src/scheduler.c
> @@ -47,6 +47,7 @@
> #include "net_os.h"
> #include "mpr_selector_set.h"
> #include "olsr_random.h"
> +#include "common/avl.h"
>
> #include <sys/times.h>
>
> @@ -74,8 +75,44 @@ static struct list_node socket_head = { &socket_head, &socket_head };
>
> /* Prototypes */
> static void walk_timers(uint32_t *);
> +static void walk_timers_cleanup(void);
> static void poll_sockets(void);
> static uint32_t calc_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val);
> +static void olsr_cleanup_timer(struct timer_entry *timer);
> +
> +struct avl_tree timer_cleanup_tree;
> +
> +struct timer_cleanup_entry {
> + struct avl_node avl;
> + struct timer_entry * timer;
> +};
> +
> +/* static inline struct timer_cleanup_entry * node2timercleanup(struct avl_node *ptr) */
> +AVLNODE2STRUCT(node2timercleanup, struct timer_cleanup_entry, avl);
> +
> +/**
> + * Loop over all timer cleanup entries and put the iterated entry in timer
> + */
> +#define OLSR_FOR_ALL_TIMERS_CLEANUP(timer) \
> +{ \
> + struct avl_node *timer_avl_node, *timer_avl_node_next; \
> + for (timer_avl_node = avl_walk_first(&timer_cleanup_tree); \
> + timer_avl_node; timer_avl_node = timer_avl_node_next) { \
> + timer_avl_node_next = avl_walk_next(timer_avl_node); \
> + timer = node2timercleanup(timer_avl_node);
> +#define OLSR_FOR_ALL_TIMER_CLEANUP_END(timer) }}
> +
> +static int avl_comp_timer(const void *entry1, const void *entry2) {
> + if (entry1 < entry2) {
> + return -1;
> + }
> +
> + if (entry1 > entry2) {
> + return -1;
This should be 'return 1;' ofcourse
Corrected locally.
> + }
> +
> + return 0;
> +}
>
> /*
> * A wrapper around times(2). Note, that this function has some
> @@ -504,6 +541,7 @@ void olsr_scheduler(void)
>
> /* Process timers */
> walk_timers(&timer_last_run);
> + walk_timers_cleanup();
>
> if (state != RUNNING) {
> break;
> @@ -530,6 +568,7 @@ void olsr_scheduler(void)
> /* Read incoming data and handle it immediiately */
> handle_fds(next_interval);
> }
> + walk_timers_cleanup();
>
> state = ENDED;
> }
> @@ -583,6 +622,8 @@ olsr_init_timers(void)
> last_tv = first_tv;
> now_times = olsr_times();
>
> + avl_init(&timer_cleanup_tree, avl_comp_timer);
> +
> for (idx = 0; idx < TIMER_WHEEL_SLOTS; idx++) {
> list_head_init(&timer_wheel[idx]);
> }
> @@ -638,6 +679,10 @@ walk_timers(uint32_t * last_run)
> list_add_after(&tmp_head_node, timer_node);
> timers_walked++;
>
> + if (timer->timer_flags & OLSR_TIMER_REMOVED) {
> + continue;
> + }
> +
> /* Ready to fire ? */
> if (TIMED_OUT(timer->timer_clock)) {
>
> @@ -694,6 +739,16 @@ walk_timers(uint32_t * last_run)
> *last_run = now_times;
> }
>
> +static void walk_timers_cleanup(void) {
> + struct timer_cleanup_entry * timer;
> +
> + OLSR_FOR_ALL_TIMERS_CLEANUP(timer) {
> + olsr_cleanup_timer(timer->timer);
> + avl_delete(&timer_cleanup_tree, &timer->avl);
> + free(timer);
> + } OLSR_FOR_ALL_TIMER_CLEANUP_END(slot)
> +}
> +
> /**
> * Stop and delete all timers.
> */
> @@ -711,6 +766,7 @@ olsr_flush_timers(void)
> olsr_stop_timer(list2timer(timer_head_node->next));
> }
> }
> + walk_timers_cleanup();
> }
>
> /**
> @@ -858,7 +914,8 @@ void
> olsr_stop_timer(struct timer_entry *timer)
> {
> /* It's okay to get a NULL here */
> - if (!timer) {
> + if (!timer //
> + || (timer->timer_flags & OLSR_TIMER_REMOVED)) {
> return;
> }
>
> @@ -868,11 +925,45 @@ olsr_stop_timer(struct timer_entry *timer)
> timer->timer_cookie->ci_name, timer, timer->timer_cb_context);
>
>
> + timer->timer_flags &= ~OLSR_TIMER_RUNNING;
> + timer->timer_flags |= OLSR_TIMER_REMOVED;
> +
> + {
> + struct timer_cleanup_entry * node = olsr_malloc(sizeof(struct timer_cleanup_entry), "timer cleanup entry");
> + node->avl.key = timer;
> + node->timer = timer;
> + if (avl_insert(&timer_cleanup_tree, &node->avl, AVL_DUP_NO) == -1) {
> + /* duplicate */
> + free(node);
> + }
> + }
> +}
> +
> +/**
> + * Clean up a timer.
> + *
> + * @param timer the timer_entry that shall be cleaned up
> + */
> +static void
> +olsr_cleanup_timer(struct timer_entry *timer)
> +{
> + /* It's okay to get a NULL here */
> + if (!timer //
> + || !(timer->timer_flags & OLSR_TIMER_REMOVED)) {
> + return;
> + }
> +
> + assert(timer->timer_cookie); /* we want timer cookies everywhere */
> +
> + OLSR_PRINTF(7, "TIMER: cleanup %s timer %p, ctx %p\n",
> + timer->timer_cookie->ci_name, timer, timer->timer_cb_context);
> +
> +
> /*
> * Carve out of the existing wheel_slot and free.
> */
> list_remove(&timer->timer_list);
> - timer->timer_flags &= ~OLSR_TIMER_RUNNING;
> + timer->timer_flags &= ~OLSR_TIMER_REMOVED;
> olsr_cookie_usage_decr(timer->timer_cookie->ci_id);
>
> olsr_cookie_free(timer_mem_cookie, timer);
> diff --git a/src/scheduler.h b/src/scheduler.h
> index a18198b..6afc791 100644
> --- a/src/scheduler.h
> +++ b/src/scheduler.h
> @@ -90,6 +90,7 @@ LISTNODE2STRUCT(list2timer, struct timer_entry, timer_list);
>
> /* Timer flags */
> #define OLSR_TIMER_RUNNING ( 1 << 0) /* this timer is running */
> +#define OLSR_TIMER_REMOVED ( 1 << 1) /* this timer is tagged for removal */
>
> /* Timers */
> void olsr_init_timers(void);
>
--
Ferry Huberts
More information about the Olsr-dev
mailing list