FreeBSD/sys/netpfil/ipfw/ip_dn_io.c
/*
 * The timer handler for dummynet. Time is computed in ticks, but
 * but the code is tolerant to the actual rate at which this is called.
 * Once complete, the function reschedules itself for the next tick.
 */
The timer handler for dummynet. Time is computed in ticks, but
but the code is tolerant to the actual rate at which this is called.
Once complete, the function reschedules itself for the next tick.
The timer handler for dummynet . Time is computed in ticks but but the code is tolerant to the actual rate at which this is called . Once complete the function reschedules itself for the next tick .
void
dummynet_task(void *context, int pending)
{
	struct timeval t;
	struct mq q = { NULL, NULL }; 
	CURVNET_SET((struct vnet *)context);
	DN_BH_WLOCK();
	tick_lost += pending - 1;
	getmicrouptime(&t);
	tick_last = (t.tv_sec - dn_cfg.prev_t.tv_sec) * 1000000 +
	(t.tv_usec - dn_cfg.prev_t.tv_usec);
	tick_delta = (tick_last * hz - 1000000) / hz;
	tick_delta_sum += tick_delta;
	dn_cfg.prev_t = t;
	dn_cfg.curr_time++;
	if (tick_delta_sum - tick >= 0) {
		int diff = tick_delta_sum / tick;
		dn_cfg.curr_time += diff;
		tick_diff += diff;
		tick_delta_sum %= tick;
		tick_adjustment++;
	} else if (tick_delta_sum + tick <= 0) {
		dn_cfg.curr_time--;
		tick_diff--;
		tick_delta_sum += tick;
		tick_adjustment++;
	}
	for (;;) {
		struct dn_id *p;    
		if (dn_cfg.evheap.elements == 0 ||
		    DN_KEY_LT(dn_cfg.curr_time, HEAP_TOP(&dn_cfg.evheap)->key))
			break;
		p = HEAP_TOP(&dn_cfg.evheap)->object;
		heap_extract(&dn_cfg.evheap, NULL);
		if (p->type == DN_SCH_I) {
			serve_sched(&q, (struct dn_sch_inst *)p, dn_cfg.curr_time);
		} else { 
			transmit_event(&q, (struct delay_line *)p, dn_cfg.curr_time);
		}
	}
	if (dn_cfg.expire && ++dn_cfg.expire_cycle >= dn_cfg.expire) {
		dn_cfg.expire_cycle = 0;
		dn_drain_scheduler();
		dn_drain_queue();
	}
	dn_reschedule();
	DN_BH_WUNLOCK();
	if (q.head != NULL)
		dummynet_send(q.head);
	CURVNET_RESTORE();
}
void dummynet_task ( void * context , int pending ) { struct timeval t ; struct mq q = { NULL , NULL } ; CURVNET_SET ( ( struct vnet * ) context ) ; DN_BH_WLOCK ( ) ; tick_lost += pending - 1 ; getmicrouptime ( & t ) ; tick_last = ( t . tv_sec - dn_cfg . prev_t . tv_sec ) * 1000000 + ( t . tv_usec - dn_cfg . prev_t . tv_usec ) ; tick_delta = ( tick_last * hz - 1000000 ) / hz ; tick_delta_sum += tick_delta ; dn_cfg . prev_t = t ; dn_cfg . curr_time ++ ; if ( tick_delta_sum - tick >= 0 ) { int diff = tick_delta_sum / tick ; dn_cfg . curr_time += diff ; tick_diff += diff ; tick_delta_sum %= tick ; tick_adjustment ++ ; } else if ( tick_delta_sum + tick <= 0 ) { dn_cfg . curr_time -- ; tick_diff -- ; tick_delta_sum += tick ; tick_adjustment ++ ; } for ( ; ; ) { struct dn_id * p ; if ( dn_cfg . evheap . elements == 0 || DN_KEY_LT ( dn_cfg . curr_time , HEAP_TOP ( & dn_cfg . evheap ) -> key ) ) break ; p = HEAP_TOP ( & dn_cfg . evheap ) -> object ; heap_extract ( & dn_cfg . evheap , NULL ) ; if ( p -> type == DN_SCH_I ) { serve_sched ( & q , ( struct dn_sch_inst * ) p , dn_cfg . curr_time ) ; } else { transmit_event ( & q , ( struct delay_line * ) p , dn_cfg . curr_time ) ; } } if ( dn_cfg . expire && ++ dn_cfg . expire_cycle >= dn_cfg . expire ) { dn_cfg . expire_cycle = 0 ; dn_drain_scheduler ( ) ; dn_drain_queue ( ) ; } dn_reschedule ( ) ; DN_BH_WUNLOCK ( ) ; if ( q . head != NULL ) dummynet_send ( q . head ) ; CURVNET_RESTORE ( ) ; }
The timer handler for dummynet.
The timer handler for dummynet .
/* queue to accumulate results */ /* Update number of lost(coalesced) ticks. */ /* Last tick duration (usec). */ /* Last tick vs standard tick difference (usec). */ /* Accumulated tick difference (usec). */ /*
	* Adjust curr_time if the accumulated tick difference is
	* greater than the 'standard' tick. Since curr_time should
	* be monotonically increasing, we do positive adjustments
	* as required, and throttle curr_time in case of negative
	* adjustment.
	*/ /* serve pending events, accumulate in q */ /* generic parameter to handler */ /* extracted a delay line */