On Feb 08, 2004 at 10:34, Greg Fausak greg@august.net wrote:
I'm thinking about a timer variable. Something like:
[...]
void set_timer_val( struct timer_link *new_tl, enum lists list_id, unsigned int timeout ) { struct timer* list;
if (list_id<FR_TIMER_LIST || list_id>=NR_OF_TIMER_LISTS) { LOG(L_CRIT, "ERROR: set_timer: unkown list: %d\n",
list_id); #ifdef EXTRA_DEBUG abort(); #endif return; }
list= &(timertable->timers[ list_id ]); lock(list->mutex); /* check first if we are on the "detached" timer_routine list, * if so do nothing, the timer is not valid anymore * (sideffect: reset_timer ; set_timer is not safe, a reseted timer * might be lost, depending on this race condition ) */ if (new_tl->timer_list==DETACHED_LIST){ LOG(L_CRIT, "WARNING: set_timer called on a
"detached" timer" " -- ignoring: %p\n", new_tl); goto end; } /* make sure I'm not already on a list */ remove_timer_unsafe( new_tl ); add_timer_unsafe( list, new_tl, get_ticks()+timeout);
The problem is add_timer_unsafe always adds at the end of the corresponding timer list which must be sorted. This is a speed improvement, because we have only fixed timer values per list and if we always add at the end the list will be always sorted (and we don't need to walk through it). If you add a variable timeout (not a fixed one) you won't have this property anymore. The problem with walking the list and comparing timeouts (to keep it sorted even if timeout is variable) is this list can get pretty big. 10000 entries is not unusual and it could get to 600000 entries in the worst case (on 5000cps capable machine under extreme stress conditions). It gets even worse: you have to lock the list when you walk it so you would prevent other ser processes from accessing the list during this time. It would have a pretty big performance impact under stress conditions.
Andrei