/** * Start a new timer. * * @param relative time expressed in milliseconds * @param jitter expressed in percent * @param timer callback function * @param context for the callback function * @return a pointer to the created entry */ struct timer_entry * olsr_start_timer(unsigned int rel_time, uint8_t jitter_pct, bool periodical, timer_cb_func cb_func, void *context, struct olsr_cookie_info *ci) { struct timer_entry *timer; if (ci == NULL) { ci = def_timer_ci; } assert(cb_func); timer = olsr_cookie_malloc(timer_mem_cookie); /* * Compute random numbers only once. */ if (!timer->timer_random) { timer->timer_random = random(); } /* Fill entry */ timer->timer_clock = calc_jitter(rel_time, jitter_pct, timer->timer_random); timer->timer_cb = cb_func; timer->timer_cb_context = context; timer->timer_jitter_pct = jitter_pct; timer->timer_flags = OLSR_TIMER_RUNNING; /* The cookie is used for debugging to traceback the originator */ timer->timer_cookie = ci; olsr_cookie_usage_incr(ci->ci_id); /* Singleshot or periodical timer ? */ timer->timer_period = periodical ? rel_time : 0; /* * Now insert in the respective timer_wheel slot. */ list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK], &timer->timer_list); OLSR_PRINTF(7, "TIMER: start %s timer %p firing in %s, ctx %p\n", ci->ci_name, timer, olsr_clock_string(timer->timer_clock), context); return timer; }
/* * Allocate a fixed amount of memory based on a passed in cookie type. */ void * olsr_cookie_malloc(struct olsr_cookie_info *ci) { void *ptr; struct olsr_cookie_mem_brand *branding; struct list_node *free_list_node; #ifdef OLSR_COOKIE_DEBUG bool reuse = false; #endif /* * Check first if we have reusable memory. */ if (!ci->ci_free_list_usage) { /* * No reusable memory block on the free_list. */ ptr = calloc(1, ci->ci_size + sizeof(struct olsr_cookie_mem_brand)); if (!ptr) { const char *const err_msg = strerror(errno); OLSR_PRINTF(1, "OUT OF MEMORY: %s\n", err_msg); olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %s\n", err_msg); olsr_exit(ci->ci_name, EXIT_FAILURE); } } else { /* * There is a memory block on the free list. * Carve it out of the list, and clean. */ free_list_node = ci->ci_free_list.next; list_remove(free_list_node); ptr = (void *)free_list_node; memset(ptr, 0, ci->ci_size); ci->ci_free_list_usage--; #ifdef OLSR_COOKIE_DEBUG reuse = true; #endif } /* * Now brand mark the end of the memory block with a short signature * indicating presence of a cookie. This will be checked against * When the block is freed to detect corruption. */ branding = (struct olsr_cookie_mem_brand *)ARM_NOWARN_ALIGN(((unsigned char *)ptr + ci->ci_size)); memcpy(&branding->cmb_sig, "cookie", 6); branding->cmb_id = ci->ci_id; /* Stats keeping */ olsr_cookie_usage_incr(ci->ci_id); #ifdef OLSR_COOKIE_DEBUG OLSR_PRINTF(1, "MEMORY: alloc %s, %p, %u bytes%s\n", ci->ci_name, ptr, ci->ci_size, reuse ? ", reuse" : ""); #endif return ptr; }