Example #1
0
ticks_t wait_handler(ticks_t ti, struct timer_ln *wait_tl, void *data)
{
	struct cell *p_cell;
	ticks_t ret;

	p_cell = (struct cell *)data;
#ifdef TIMER_DEBUG
	LM_DBG("WAIT timer hit @%d for %p (timer_lm %p)\n", ti, p_cell, wait_tl);
#endif

#ifdef TM_DEL_UNREF
	/* stop cancel timers if any running */
	if(is_invite(p_cell))
		cleanup_localcancel_timers(p_cell);
	/* remove the cell from the hash table */
	LOCK_HASH(p_cell->hash_index);
	remove_from_hash_table_unsafe(p_cell);
	UNLOCK_HASH(p_cell->hash_index);
	p_cell->flags |= T_IN_AGONY;
	if(t_linked_timers(p_cell)) {
		UNREF_FREE(p_cell, 0);
	} else {
		UNREF_FREE(p_cell, 1);
	}
	ret = 0;
#else  /* TM_DEL_UNREF */
	if(p_cell->flags & T_IN_AGONY) {
		/* delayed delete */
		/* we call delete now without any locking on hash/ref_count;
		   we can do that because delete_handler is only entered after
		   the delete timer was installed from wait_handler, which
		   removed transaction from hash table and did not destroy it
		   because some processes were using it; that means that the
		   processes currently using the transaction can unref and no
		   new processes can ref -- we can wait until ref_count is
		   zero safely without locking
		*/
		ret = delete_cell(p_cell, 0 /* don't unlock on return */);
	} else {
		/* stop cancel timers if any running */
		if(is_invite(p_cell))
			cleanup_localcancel_timers(p_cell);
		/* remove the cell from the hash table */
		LOCK_HASH(p_cell->hash_index);
		remove_from_hash_table_unsafe(p_cell);
		p_cell->flags |= T_IN_AGONY;
		/* delete (returns with UNLOCK-ed_HASH) */
		ret = delete_cell(p_cell, 1 /* unlock on return */);
	}
#endif /* TM_DEL_UNREF */
	return ret;
}
Example #2
0
inline static void wait_handler( struct timer_link *wait_tl )
{
	struct cell *p_cell;

	p_cell = get_wait_timer_payload( wait_tl );
#ifdef EXTRA_DEBUG
	if (p_cell->damocles) {
		LM_ERR("transaction %p scheduled for deletion and"
			" called from WAIT timer\n",p_cell);
		abort();
	}
	LM_DBG("WAIT timer hit\n");
#endif

	/* stop cancel timers if any running */
	if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );

	/* the transaction is already removed from WT_LIST by the timer */
	/* remove the cell from the hash table */
	LM_DBG("removing %p from table \n", p_cell );
	LOCK_HASH( p_cell->hash_index );
	remove_from_hash_table_unsafe(  p_cell );
	/* jku: no more here -- we do it when we put a transaction on wait */
#ifdef EXTRA_DEBUG
	p_cell->damocles = 1;
#endif
	/* delete (returns with UNLOCK-ed_HASH) */
	delete_cell( p_cell, 1 /* unlock on return */ );
	LM_DBG("done\n");
}