On Feb 08, 2004 at 10:34, Greg Fausak <greg(a)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