Example #1
0
/* slow timer main function, never exists
 * This function is intended to be executed in a special separated process
 * (the "slow" timer) which will run the timer handlers of all the registered
 * timers not marked as "fast". The ideea is to execute the fast timers in the
 * "main" timer process, as accurate as possible and defer the execution of the  * timers marked as "slow" to the "slow" timer.
 * Implementation details:
 *  - it waits for a signal and then wakes up and processes
 *    all the lists in slow_timer_lists from [s_idx, t_idx). It will
 *   -it  increments *s_idx (at the end it will be == *t_idx)
 *   -all list operations are protected by the "slow" timer lock
 */
void slow_timer_main()
{
	int n;
	ticks_t ret;
	struct timer_ln* tl;
	unsigned short i;
	
	in_slow_timer=1; /* mark this process as the slow timer */
	while(1){
#ifdef USE_SIGWAIT
		n=sigwait(&slow_timer_sset, 0);
#else
		n=sigwaitinfo(&slow_timer_sset, 0);
#endif
		if (n==-1){
			if (errno==EINTR) continue; /* some other signal, ignore it */
			LOG(L_ERR, "ERROR: slow_timer_main: sigwaitinfo failed: %s [%d]\n",
					strerror(errno), errno);
			sleep(1);
			/* try to continue */
		}
		LOCK_SLOW_TIMER_LIST();
		while(*s_idx!=*t_idx){
			i= *s_idx%SLOW_LISTS_NO;
			while(slow_timer_lists[i].next!=
					(struct timer_ln*)&slow_timer_lists[i]){
				tl=slow_timer_lists[i].next;
				_timer_rm_list(tl);
				tl->next=tl->prev=0;
#ifdef TIMER_DEBUG
				tl->expires_no++;
#endif
				SET_RUNNING_SLOW(tl);
				UNLOCK_SLOW_TIMER_LIST();
					ret=tl->f(*ticks, tl, tl->data);
					if (ret==0){
						/* one shot */
						UNSET_RUNNING_SLOW();
						LOCK_SLOW_TIMER_LIST();
					}else{
						/* not one shot, re-add it */
						LOCK_TIMER_LIST(); /* add it to the "main"  list */
							RESET_SLOW_LIST(tl);
							if (ret!=(ticks_t)-1) /* != periodic */
								tl->initial_timeout=ret;
							_timer_add(*ticks, tl);
						UNLOCK_TIMER_LIST();
						LOCK_SLOW_TIMER_LIST();
						UNSET_RUNNING_SLOW();
					}
			}
			(*s_idx)++;
		}
		UNLOCK_SLOW_TIMER_LIST();
	}
	
}
Example #2
0
int timer_add_safe(struct timer_ln* tl, ticks_t delta)
#endif
{
	int ret;

	LOCK_TIMER_LIST();
	if (tl->flags & F_TIMER_ACTIVE){
#ifdef TIMER_DEBUG
		LOG(timerlog, "timer_add called on an active timer %p (%p, %p),"
					" flags %x\n", tl, tl->next, tl->prev, tl->flags);
		LOG(timerlog, "WARN: -timer_add-; called from %s(%s):%d\n",
					func, file, line);
		LOG(timerlog, "WARN: -timer_add-: added %d times"
					", last from: %s(%s):%d, deleted %d times"
					", last from: %s(%s):%d, init %d times, expired %d \n",
					tl->add_calls, tl->add_func, tl->add_file, tl->add_line,
					tl->del_calls, tl->del_func, tl->del_file, tl->del_line,
					tl->init, tl->expires_no);
#else
		LM_DBG("timer_add called on an active timer %p (%p, %p),"
					" flags %x\n", tl, tl->next, tl->prev, tl->flags);
#endif
		ret=-1; /* refusing to add active or non-reinit. timer */
		goto error;
	}
	tl->initial_timeout=delta;
	if ((tl->next!=0) || (tl->prev!=0)){
		LM_CRIT("timer_add: called with linked timer: %p (%p, %p)\n",
				tl, tl->next, tl->prev);
		ret=-1;
		goto error;
	}
	tl->flags|=F_TIMER_ACTIVE;
#ifdef TIMER_DEBUG
	tl->add_file=file;
	tl->add_func=func;
	tl->add_line=line;
	tl->add_calls++;
#endif
	ret=_timer_add(*ticks, tl);
error:
	UNLOCK_TIMER_LIST();
	return ret;
}
Example #3
0
/* called from timer_handle, must be called with the timer lock held
 * WARNING: expired one shot timers are _not_ automatically reinit
 *          (because they could have been already freed from the timer
 *           handler so a reinit would not be safe!) */
inline static void timer_list_expire(ticks_t t, struct timer_head* h
#ifdef USE_SLOW_TIMER
										, struct timer_head* slow_l,
										slow_idx_t slow_mark
#endif
																	)
{
	struct timer_ln * tl;
	ticks_t ret;
#ifdef TIMER_DEBUG
	struct timer_ln* first;
	int i=0;

	first=h->next;
#endif

	/*LM_DBG("@ ticks = %lu, list =%p\n",
			(unsigned long) *ticks, h);
	*/
	while(h->next!=(struct timer_ln*)h){
		tl=h->next;
#ifdef TIMER_DEBUG /* FIXME: replace w/ EXTRA_DEBUG */
		if (tl==0){
			LM_CRIT("timer_list_expire: tl=%p, h=%p {%p, %p}\n",
					tl, h, h->next, h->prev);
			abort();
		}else if((tl->next==0) || (tl->prev==0)){
			LM_CRIT("timer_list_expire: @%d tl=%p "
					"{ %p, %p, %d, %d, %p, %p, %04x, -},"
					" h=%p {%p, %p}\n", t,
					tl,  tl->next, tl->prev, tl->expire, tl->initial_timeout,
					tl->data, tl->f, tl->flags,
					h, h->next, h->prev);
			LM_CRIT("-timer_list_expire-: cycle %d, first %p,"
						"running %p\n", i, first, *running_timer);
			LM_CRIT("-timer_list_expire-: added %d times"
						", last from: %s(%s):%d, deleted %d times"
						", last from: %s(%s):%d, init %d times, expired %d \n",
						tl->add_calls,
						tl->add_func, tl->add_file, tl->add_line,
						tl->del_calls,
						tl->del_func, tl->del_file, tl->del_line,
						tl->init, tl->expires_no);
			abort();
		}
		i++;
#endif
		_timer_rm_list(tl); /* detach */
#ifdef USE_SLOW_TIMER
		if (IS_FAST_TIMER(tl)){
#endif
		/* if fast timer */
			SET_RUNNING(tl);
			tl->next=tl->prev=0; /* debugging */
#ifdef TIMER_DEBUG
			tl->expires_no++;
#endif
			UNLOCK_TIMER_LIST(); /* acts also as write barrier */
				ret=tl->f(t, tl, tl->data);
				/* reset the configuration group handles */
				cfg_reset_all();
				if (ret==0){
					UNSET_RUNNING();
					LOCK_TIMER_LIST();
				}else{
					/* not one-shot, re-add it */
					LOCK_TIMER_LIST();
					if (ret!=(ticks_t)-1) /* ! periodic */
						tl->initial_timeout=ret;
					_timer_add(t, tl);
					UNSET_RUNNING();
				}
#ifdef USE_SLOW_TIMER
		}else{
			/* slow timer */
			SET_SLOW_LIST(tl);
			tl->slow_idx=slow_mark; /* current index */
			/* overflow check in timer_handler*/
			_timer_add_list(slow_l, tl);

		}
#endif
	}
}
Example #4
0
void slow_timer_main()
{
	int n;
	ticks_t ret;
	struct timer_ln* tl;
	unsigned short i;
#ifdef USE_SIGWAIT
	int sig;
#endif

	in_slow_timer=1; /* mark this process as the slow timer */
	while(1){
#ifdef USE_SIGWAIT
		n=sigwait(&slow_timer_sset, &sig);
#else
		n=sigwaitinfo(&slow_timer_sset, 0);
#endif
		if (n==-1){
			if (errno==EINTR) continue; /* some other signal, ignore it */
			LM_ERR("sigwaitinfo failed: %s [%d]\n", strerror(errno), errno);
			sleep(1);
			/* try to continue */
		}
#ifdef USE_SIGWAIT
	if (sig!=SLOW_TIMER_SIG){
#ifdef __OS_darwin
		/* on darwin sigwait is buggy: it will cause extreme slow down
		 *  on signal delivery for the signals it doesn't wait on
		 *  (on darwin 8.8.0, g4 1.5Ghz I've measured a 36s delay!).
		 * To work arround this bug, we sigwait() on all the signals we
		 * are interested in ser and manually call the master signal handler
		 * if the signal!= slow timer signal -- andrei */
		sig_usr(sig);
#endif
		continue;
	}
#endif
		/* update the local cfg if needed */
		cfg_update();

		LOCK_SLOW_TIMER_LIST();
		while(*s_idx!=*t_idx){
			i= *s_idx%SLOW_LISTS_NO;
			while(slow_timer_lists[i].next!=
					(struct timer_ln*)&slow_timer_lists[i]){
				tl=slow_timer_lists[i].next;
				_timer_rm_list(tl);
				tl->next=tl->prev=0;
#ifdef TIMER_DEBUG
				tl->expires_no++;
#endif
				SET_RUNNING_SLOW(tl);
				UNLOCK_SLOW_TIMER_LIST();
					ret=tl->f(*ticks, tl, tl->data);
					/* reset the configuration group handles */
					cfg_reset_all();
					if (ret==0){
						/* one shot */
						UNSET_RUNNING_SLOW();
						LOCK_SLOW_TIMER_LIST();
					}else{
						/* not one shot, re-add it */
						LOCK_TIMER_LIST(); /* add it to the "main"  list */
							RESET_SLOW_LIST(tl);
							if (ret!=(ticks_t)-1) /* != periodic */
								tl->initial_timeout=ret;
							_timer_add(*ticks, tl);
						UNLOCK_TIMER_LIST();
						LOCK_SLOW_TIMER_LIST();
						UNSET_RUNNING_SLOW();
					}
			}
			(*s_idx)++;
		}
		UNLOCK_SLOW_TIMER_LIST();
	}

}