Example #1
0
void print_timer_list(struct list_link *head)
{
	struct list_link *ll;

	DBG("DEBUG:pike:print_timer_list --->\n");
	for ( ll=head->next ; ll!=head; ll=ll->next) {
		DBG("\t %p [byte=%x](expires=%d)\n",
			ll, ll2ipnode(ll)->byte, ll2ipnode(ll)->expires);
	}
}
Example #2
0
File: timer.c Project: OPSF/uClinux
/* "head" list MUST not be empty */
void check_and_split_timer(struct list_link *head, int time,
							struct list_link *split, unsigned char *mask)
{
	struct list_link *ll;
	unsigned char b;
	int i;

	/*  reset the mask */
	for(i=0;i<32;mask[i++]=0);

	ll = head->next;
	while( ll!=head && ll2ipnode(ll)->expires<=time) {
		DBG("DEBUG:pike:check_and_split_timer: splitting %p(%p,%p)node=%p\n",
			ll,ll->prev,ll->next,ll2ipnode(ll));
		b = ll2ipnode(ll)->branch;
		ll=ll->next;
		/*DBG("DEBUG:pike:check_and_split_timer: b=%d; [%d,%d]\n",
				b,b>>3,1<<(b&0x07));*/
		mask[b>>3] |= (1<<(b&0x07));
	}

	if (ll==head->next) {
		/* nothing to return */
		split->next = split->prev = split;
	} else {
		/* the detached list begins with current beginning */
		split->next = head->next;
		split->next->prev = split;
		/* and we mark the end of the split list */
		split->prev = ll->prev;
		split->prev->next = split;
		/* the shortened list starts from where we suspended */
		head->next = ll;
		ll->prev = head;
	}

	DBG("DEBUG:pike:check_and_split_timer: succ. to split (h=%p)(p=%p,n=%p)\n",
		head,head->prev,head->next);
	return;
}
Example #3
0
/* "head" list MUST not be empty */
void check_and_split_timer(struct list_link *head, unsigned int time,
							struct list_link *split, unsigned char *mask)
{
	struct list_link *ll;
	struct ip_node   *node;
	unsigned char b;
	int i;

	/*  reset the mask */
	for(i=0;i<32;mask[i++]=0);

	ll = head->next;
	while( ll!=head && (node=ll2ipnode(ll))->expires<=time) {
		LM_DBG("splitting %p(%p,%p)node=%p\n", ll,ll->prev,ll->next, node);
		/* mark the node as expired and un-mark it as being in timer list */
		node->flags |= NODE_EXPIRED_FLAG;
		node->flags &= ~NODE_INTIMER_FLAG;
		b = node->branch;
		ll=ll->next;
		/*LM_DBG("b=%d; [%d,%d]\n",	b,b>>3,1<<(b&0x07));*/
		mask[b>>3] |= (1<<(b&0x07));
	}

	if (ll==head->next) {
		/* nothing to return */
		split->next = split->prev = split;
	} else {
		/* the detached list begins with current beginning */
		split->next = head->next;
		split->next->prev = split;
		/* and we mark the end of the split list */
		split->prev = ll->prev;
		split->prev->next = split;
		/* the shortened list starts from where we suspended */
		head->next = ll;
		ll->prev = head;
	}

	LM_DBG("succ. to split (h=%p)(p=%p,n=%p)\n", head,head->prev,head->next);
	return;
}
Example #4
0
void clean_routine(unsigned int ticks , void *param)
{
	static unsigned char mask[32];  /* 256 positions mask */
	struct list_link head;
	struct list_link *ll;
	struct ip_node   *dad;
	struct ip_node   *node;
	int i;

	/* LM_DBG("entering (%d)\n",ticks); */
	/* before locking check first if the list is not empty and if can
	 * be at least one element removed */
	if ( is_list_empty( timer )) return; /* quick exit */

	/* get the expired elements */
	lock_get( timer_lock );
	/* check again for empty list */
	if (is_list_empty(timer) || (ll2ipnode(timer->next)->expires>ticks )){
		lock_release( timer_lock );
		return;
	}
	check_and_split_timer( timer, ticks, &head, mask);
	/*print_timer_list(timer);*/ /* debug */
	lock_release( timer_lock );
	/*print_tree( 0 );*/  /*debug*/

	/* got something back? */
	if ( is_list_empty(&head) )
		return;

	/* process what we got -> don't forget to lock the tree!! */
	for(i=0;i<MAX_IP_BRANCHES;i++) {
		/* if no element from this branch -> skip it */
		if ( ((mask[i>>3])&(1<<(i&0x07)))==0 )
			continue;

		lock_tree_branch( i );
		for( ll=head.next ; ll!=&head ; ) {
			node = ll2ipnode( ll );
			ll = ll->next;
			/* skip nodes from a different branch */
			if (node->branch!=i)
				continue;

			/* unlink the node -> the list will get shorter and it will be
			 * faster for the next branches to process it */
			ll->prev->prev->next = ll;
			ll->prev = ll->prev->prev;
			node->expires = 0;
			node->timer_ll.prev = node->timer_ll.next = 0;
			if ( node->flags&NODE_EXPIRED_FLAG )
				node->flags &= ~NODE_EXPIRED_FLAG;
			else
				continue;

			/* process the node */
			LM_DBG("clean node %p (kids=%p; hits=[%d,%d];leaf=[%d,%d])\n",
				node,node->kids,
				node->hits[PREV_POS],node->hits[CURR_POS],
				node->leaf_hits[PREV_POS],node->leaf_hits[CURR_POS]);
			/* if it's a node, leaf for an ipv4 address inside an
			 * ipv6 address -> just remove it from timer it will be deleted
			 * only when all its kids will be deleted also */
			if (node->kids) {
				assert( node->flags&NODE_IPLEAF_FLAG );
				node->flags &= ~NODE_IPLEAF_FLAG;
				node->leaf_hits[CURR_POS] = 0;
			} else {
				/* if the node has no prev, means its a top branch node -> just
				 * removed and destroy it */
				if (node->prev!=0) {
					/* if this is the last kid, we have to put the father
					 * into timer list */
					if (node->prev->kids==node && node->next==0) {
						/* this is the last kid node */
						dad = node->prev;
						/* put it in the list only if it's not an IP leaf
						 * (in this case, it's already there) */
						if ( !(dad->flags&NODE_IPLEAF_FLAG) ) {
							lock_get(timer_lock);
							dad->expires = get_ticks() + timeout;
							assert( !has_timer_set(&(dad->timer_ll)) );
							append_to_timer( timer, &(dad->timer_ll));
							dad->flags |= NODE_INTIMER_FLAG;
							lock_release(timer_lock);
						} else {
							assert( has_timer_set(&(dad->timer_ll)) );
						}
					}
				}
				LM_DBG("rmv node %p[%d] \n", node,node->byte);
				/* del the node */
				remove_node( node);
			}
		} /* for all expired elements */
		unlock_tree_branch( i );
	} /* for all branches */
}