Пример #1
0
/*
 * Called when the infrastructure removes a queue (e.g. flowset
 * is reconfigured). Nothing to do if we did not 'own' the queue,
 * otherwise remove it from the right heap and adjust the sum
 * of weights.
 */
static int
wf2qp_free_queue(struct dn_queue *q, int safe)
{
	struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)q;
	struct wf2qp_si *si = (struct wf2qp_si *)(q->_si + 1);

	if (alg_fq->S >= alg_fq->F + 1)
		return 0;	/* nothing to do, not in any heap */

	/* queue is in a scheduler heap */
	if (safe)	/* do not delete in safe mode */
		return 1;

	si->wsum -= q->fs->fs.par[0];
	if (si->wsum > 0)
		si->inv_wsum = ONE_FP/si->wsum;

	/* extract from the heap. XXX TODO we may need to adjust V
	 * to make sure the invariants hold.
	 */
	if (q->mq.head == NULL) {
		heap_extract(&si->idle_heap, q);
	} else if (DN_KEY_LT(si->V, alg_fq->S)) {
		heap_extract(&si->ne_heap, q);
	} else {
		heap_extract(&si->sch_heap, q);
	}
	return 0;
}
void outputSorted(const Person people[],
        int numPeople,
        int (* compare)(const void *pKey1, const void *pKey2))
{
    Heap heap;
    void *data;
    int i;

    /* Initialize heap */
    heap_init(&heap, compare, NULL);

    /* Add people to heap */
    for (i = 0; i < numPeople; ++i)
        if (heap_insert(&heap, &people[i]) != 0)
            fatalError("Failed to insert person into heap");

    /* Extract and output people from heap */
    while (heap_size(&heap) > 0) {
        if (heap_extract(&heap, &data) != 0)
            fatalError("Failed to extract person from heap");
        outputPerson((const Person *)data);
    }

    /* Destroy heap */
    heap_destroy(&heap);
}
Пример #3
0
/*
 * Primary function for DI APSP.
 */
void di_apsp(int n, float* dist, float* graph,
             int* p, int* q, std::vector<int>* L, std::vector<int>* R,
             std::list<int>* bucket_heap, int* b_num,
             std::list<int>::iterator* iters) {
    
    // Initialize
    di_init(n, dist, graph, p, q, L, R, bucket_heap, b_num, iters);
    int u, v, pair;

    //Main loop
    while (1) {

        // Get min (u,v) pair from the heap.
        // Break the loop if heap was empty.
        pair = heap_extract(bucket_heap, b_num, n, iters);
        if (pair < 0) break;
        u = pair/n;
        v = pair%n;
       
        // Add to relevant lists
        L[p[u*n + v]*n + v].push_back(u);
        R[u*n + q[u*n + v]].push_back(v);

        // Examine through the lists.
        di_lists(n, u, v, dist, graph, 
            p, q, L, R, bucket_heap, b_num, iters);
    }
}
Пример #4
0
int * dijkstra(graph g, int from, int*tree, int (*add)(int, int)){
	int * somme, i, act;/*Commistione linguistica che bonato ama! xD*/
	heap_t *heap;
	
	somme = malloc(sizeof(int) * g->v);
	
	assert(somme != NULL);
	
	/*Piazzo tutto a -1 che in binario è 11111111....1111 ... fino alla nausea... 1111*/
	memset(somme, 0xff, g->v * sizeof(int));

	/*Good! Ora però la prima va a 0!*/
	somme[from] = 0;

	/*Ci siamo quasi...*/
	/*ora le heap!*/
	heap = heap_make(somme, g->v, heapcmp, sizeof(int));
	/*Metto a TRUE la flag *connected*/
	g->connesso = 1;
	/*Ultimissima cosa: inizializzo l'albero delle visite ad una foresta di alberi di un solo elemento*/
	for(i = 0; i < g->v; i++)
		tree[i] = i;
	/* Ora il ciclo, prepariamo l'assorbente xD*/
	while(!heap_is_empty(heap)){
		/* Estraggo il primo elemento*/
		from = heap_extract(heap);
		/* Se la distanza per arrivare è ancora infinita (-1), significa che questa parte del
		 * Grafo non è mai stata raggiunta da nessun arco e quindi è disconnessa dalla componente
		 * In cui è presente il nodo di partenza, e quindi, visto che questo è il massimo possibili
		 * tutti gli altri elementi nella heap avranno lo stesso valore, quindi interrompo qui
		 * l'esecuzione */
		if(somme[from] == -1) {
			g->connesso = 0;/* Segno che il grafo non è connesso*/
			/*interrompo il ciclo*/
			break;
		}
		/*E itero tra tutto */
		for(i = 0; i < g->v; i++){
			if(g->adj[from][i]){
				/*Mi calcolo la distanza attuale + quella dell'arco tramite una funzione esterna*/
				act = add(somme[from], g->adj[from][i]);
				/*Se la somma è a -1 (non è ancora stato aggiornato) oppure il nuovo valore
				  e' inferiore a quello vecchio, lo metto uguale e aggiorno l'albero delle visite*/
				if(somme[i] == -1 || somme[i] > act){
					somme[i] = act;
					tree[i] = from;
					/*Ho aggiornato: devo fare un fix della heap che potrebbe essere andata a farsi fottere!*/
					heap_fix(heap, i);
				}
			}
		}
	}
	heap_free(heap);/*Questa non mi cancella l'array somme, quindi sono contento xD*/
	/*Bene! abbiamo finito! :)*/
	return somme;
}
Пример #5
0
void *match_thread(void *thread_args) {
    long i;
    float score;
    heap_t *heap = NULL;
    thread_args_t *args = (thread_args_t *)thread_args;

    if (args->limit) {
        // Reserve one extra slot so that we can do an insert-then-extract even
        // when "full" (effectively allows use of min-heap to maintain a
        // top-"limit" list of items).
        heap = heap_new(args->limit + 1, cmp_score);
    }

    for (
        i = args->thread_index;
        i < args->path_count;
        i += args->thread_count
    ) {
        args->matches[i].path = RARRAY_PTR(args->haystacks)[i];
        if (args->needle_bitmask == UNSET_BITMASK) {
            args->matches[i].bitmask = UNSET_BITMASK;
        }
        if (!NIL_P(args->last_needle) && args->matches[i].score == 0.0) {
            // Skip over this candidate because it didn't match last
            // time and it can't match this time either.
            continue;
        }
        args->matches[i].score = calculate_match(
            args->matches[i].path,
            args->needle,
            args->case_sensitive,
            args->always_show_dot_files,
            args->never_show_dot_files,
            args->recurse,
            args->needle_bitmask,
            &args->matches[i].bitmask
        );
        if (args->matches[i].score == 0.0) {
            continue;
        }
        if (heap) {
            if (heap->count == args->limit) {
                score = ((match_t *)HEAP_PEEK(heap))->score;
                if (args->matches[i].score >= score) {
                    heap_insert(heap, &args->matches[i]);
                    (void)heap_extract(heap);
                }
            } else {
                heap_insert(heap, &args->matches[i]);
            }
        }
    }

    return heap;
}
Пример #6
0
static int
wf2qp_enqueue(struct dn_sch_inst *_si, struct dn_queue *q, struct mbuf *m)
{
    struct dn_fsk *fs = q->fs;
    struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1);
    struct wf2qp_queue *alg_fq;
    uint64_t len = m->m_pkthdr.len;

    if (m != q->mq.head) {
	if (dn_enqueue(q, m, 0)) /* packet was dropped */
	    return 1;
	if (m != q->mq.head)	/* queue was already busy */
	    return 0;
    }

    /* If reach this point, queue q was idle */
    alg_fq = (struct wf2qp_queue *)q;

    if (DN_KEY_LT(alg_fq->F, alg_fq->S)) {
        /* F<S means timestamps are invalid ->brand new queue. */
        alg_fq->S = si->V;		/* init start time */
        si->wsum += fs->fs.par[0];	/* add weight of new queue. */
	si->inv_wsum = ONE_FP/si->wsum;
    } else { /* if it was idle then it was in the idle heap */
        heap_extract(&si->idle_heap, q);
        alg_fq->S = MAX64(alg_fq->F, si->V);	/* compute new S */
    }
    alg_fq->F = alg_fq->S + len * alg_fq->inv_w;

    /* if nothing is backlogged, make sure this flow is eligible */
    if (si->ne_heap.elements == 0 && si->sch_heap.elements == 0)
        si->V = MAX64(alg_fq->S, si->V);

    /*
     * Look at eligibility. A flow is not eligibile if S>V (when
     * this happens, it means that there is some other flow already
     * scheduled for the same pipe, so the sch_heap cannot be
     * empty). If the flow is not eligible we just store it in the
     * ne_heap. Otherwise, we store in the sch_heap.
     * Note that for all flows in sch_heap (SCH), S_i <= V,
     * and for all flows in ne_heap (NEH), S_i > V.
     * So when we need to compute max(V, min(S_i)) forall i in
     * SCH+NEH, we only need to look into NEH.
     */
    if (DN_KEY_LT(si->V, alg_fq->S)) {
        /* S>V means flow Not eligible. */
        if (si->sch_heap.elements == 0)
            D("++ ouch! not eligible but empty scheduler!");
        heap_insert(&si->ne_heap, alg_fq->S, q);
    } else {
        heap_insert(&si->sch_heap, alg_fq->F, q);
    }
    return 0;
}
Пример #7
0
/*
 * This file implements a WF2Q+ scheduler as it has been in dummynet
 * since 2000.
 * The scheduler supports per-flow queues and has O(log N) complexity.
 *
 * WF2Q+ needs to drain entries from the idle heap so that we
 * can keep the sum of weights up to date. We can do it whenever
 * we get a chance, or periodically, or following some other
 * strategy. The function idle_check() drains at most N elements
 * from the idle heap.
 */
static void
idle_check(struct wf2qp_si *si, int n, int force)
{
    struct dn_heap *h = &si->idle_heap;
    while (n-- > 0 && h->elements > 0 &&
		(force || DN_KEY_LT(HEAP_TOP(h)->key, si->V))) {
	struct dn_queue *q = HEAP_TOP(h)->object;
        struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)q;

        heap_extract(h, NULL);
        /* XXX to let the flowset delete the queue we should
	 * mark it as 'unused' by the scheduler.
	 */
        alg_fq->S = alg_fq->F + 1; /* Mark timestamp as invalid. */
        si->wsum -= q->fs->fs.par[0];	/* adjust sum of weights */
	if (si->wsum > 0)
		si->inv_wsum = ONE_FP/si->wsum;
    }
}
Пример #8
0
/* Drain events in the heap. If this operation stalls after exceeding a limit
 * in the number of events, return non-zero. Zero is success. */
static int esim_drain_heap(void)
{
	int count = 0;

	struct esim_event_t *event;
	struct esim_event_info_t *event_info;

	long long when;

	/* Extract all elements from heap */
	while (1)
	{
		/* Extract event */
		when = heap_extract(esim_event_heap, (void **) &event);
		if (heap_error(esim_event_heap))
			break;

		/* Process it */
		count++;
		esim_time = when;
		event_info = list_get(esim_event_info_list, event->id);
		assert(event_info && event_info->handler);
		event_info->handler(event->id, event->data);
		esim_event_free(event);

		/* Interrupt heap draining after exceeding a given number of
		 * events. This can happen if the event handlers of processed
		 * events keep scheduling new events, causing the heap to never
		 * finish draining. */
		if (count == ESIM_MAX_FINALIZATION_EVENTS)
		{
			esim_dump(stderr, 20);
			warning("%s: number of finalization events exceeds %d - stopped.\n%s",
				__FUNCTION__, ESIM_MAX_FINALIZATION_EVENTS,
				esim_err_finalization);
			return 1;
		}
	}

	/* Success */
	return 0;
}
int main() {
	int n, m; scanf("%d%d", &n, &m);

	edge es[2*m];
	for (int i = 0; i < m; i++) {
		int vi, ui, w; scanf("%d%d%d", &vi, &ui, &w);

		vertex *v = &vs[vi], *u = &vs[ui];
		es[2*i] = (edge){u, w, v->a}; v->a = &es[2*i];
		es[2*i+1] = (edge){v, w, u->a}; u->a = &es[2*i+1];
	}

	const int inf = (int)1e9;
	for (vertex *v = vs; v != vs+n; v++) {
		v->i = v - vs;
		v->d = inf;
		v->b = false;
		heap_insert(v);
	}

	int s; scanf("%d", &s);
	vs[s]->d = 0;

	for (int i = 0; i < n; i++) {
		vertex *v = heap_extract();

		v->b = true;

		for (edge *e = v->a; e != NULL; e = e->n) {
			vertex *u = e->v;
			if (!u->b && v->d + e->w < u->d) {
				u->d = v->d + e->w;
				heap_decrease(u);
			}
		}
	}

	return 0;
}
int heapsort(int h[], int tam) {
    int count, veri=0, custo=0;
    build_heap(h,tam);
    //somaglobal = 0;
    if(tam!=0) {
        while(tam>0) {
            count = tam;
            tam = heap_extract(h,count);
            veri++;
            if(veri == 2) {
                tam++;
                h[tam]+=h[tam+1];
                //val_global = h[tam];
                custo+=h[tam];
                heapify(h,0,tam);
                veri = 0;
            }
        }
        custo+=(h[tam]+h[tam+1]);
    }
    else custo = 0;
    return custo;
}
Пример #11
0
int
main(int argc, char *argv[])
{
	struct dn_heap h;
	int i, n, n2, n3;

	test_hash();
	return 0;

	/* n = elements, n2 = cycles */
	n = (argc > 1) ? atoi(argv[1]) : 0;
	if (n <= 0 || n > 1000000)
		n = 100;
	n2 = (argc > 2) ? atoi(argv[2]) : 0;
	if (n2 <= 0)
		n = 1000000;
	n3 = (argc > 3) ? atoi(argv[3]) : 0;
	bzero(&h, sizeof(h));
	heap_init(&h, n, -1);
	while (n2-- > 0) {
		uint64_t prevk = 0;
		for (i=0; i < n; i++)
			heap_insert(&h, n3 ? n-i: random(), (void *)(100+i));
		
		for (i=0; h.elements > 0; i++) {
			uint64_t k = h.p[0].key;
			if (k < prevk)
				panic("wrong sequence\n");
			prevk = k;
			if (0)
			printf("%d key %llu, val %p\n",
				i, h.p[0].key, h.p[0].object);
			heap_extract(&h, NULL);
		}
	}
	return 0;
}
Пример #12
0
int main(int argc, char **argv) {

	Heap heap;

	void *data;

	int intval[30], i;

	/*****************************************************************************
	 *                                                                            *
	 *  Initialize the heap.                                                      *
	 *                                                                            *
	 *****************************************************************************/

	heap_init(&heap, compare_int, NULL);

	/*****************************************************************************
	 *                                                                            *
	 *  Perform some heap operations.                                             *
	 *                                                                            *
	 *****************************************************************************/

	i = 0;

	intval[i] = 5;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	intval[i] = 10;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	intval[i] = 20;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	intval[i] = 1;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	intval[i] = 25;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	intval[i] = 22;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	intval[i] = 9;
	fprintf(stdout, "Inserting %03d\n", intval[i]);
	if (heap_insert(&heap, &intval[i]) != 0)
		return 1;
	print_heap(&heap);
	i++;

	while (heap_size(&heap) > 0) {

		if (heap_extract(&heap, (void **) &data) != 0)
			return 1;
		fprintf(stdout, "Extracting %03d\n", *(int *) data);
		print_heap(&heap);

	}

	/*****************************************************************************
	 *                                                                            *
	 *  Destroy the heap.                                                         *
	 *                                                                            *
	 *****************************************************************************/

	fprintf(stdout, "Destroying the heap\n");
	heap_destroy(&heap);

	return 0;

}
Пример #13
0
Character *turn_dequeue()
{
	return heap_extract(h);
}
Пример #14
0
void evg_compute_unit_free(struct evg_compute_unit_t *compute_unit)
{
	struct heap_t *event_queue;
	struct evg_uop_t *uop;
	int i;

	/* CF Engine - free uops in fetch buffer, instruction buffer, and complete queue */
	for (i = 0; i < evg_gpu_max_wavefronts_per_compute_unit; i++)
	{
		evg_uop_free(compute_unit->cf_engine.fetch_buffer[i]);
		evg_uop_free(compute_unit->cf_engine.inst_buffer[i]);
	}
	evg_uop_list_free(compute_unit->cf_engine.complete_queue);

	/* CF Engine - free structures */
	free(compute_unit->cf_engine.fetch_buffer);
	free(compute_unit->cf_engine.inst_buffer);
	linked_list_free(compute_unit->cf_engine.complete_queue);

	/* ALU Engine - free uops in event queue (heap) */
	event_queue = compute_unit->alu_engine.event_queue;
	while (heap_count(event_queue))
	{
		heap_extract(event_queue, (void **) &uop);
		uop->write_subwavefront_count++;
		if (uop->write_subwavefront_count == uop->subwavefront_count)
			evg_uop_free(uop);
	}

	/* ALU Engine - free uops in fetch queue, instruction buffer, execution buffer,
	 * and event queue. Also free CF instruction currently running. */
	evg_uop_list_free(compute_unit->alu_engine.pending_queue);
	evg_uop_list_free(compute_unit->alu_engine.finished_queue);
	evg_uop_list_free(compute_unit->alu_engine.fetch_queue);
	evg_uop_free(compute_unit->alu_engine.inst_buffer);
	evg_uop_free(compute_unit->alu_engine.exec_buffer);

	/* ALU Engine - structures */
	linked_list_free(compute_unit->alu_engine.pending_queue);
	linked_list_free(compute_unit->alu_engine.finished_queue);
	linked_list_free(compute_unit->alu_engine.fetch_queue);
	heap_free(compute_unit->alu_engine.event_queue);

	/* TEX Engine - free uop in fetch queue, instruction buffer, write buffer. */
	evg_uop_list_free(compute_unit->tex_engine.pending_queue);
	evg_uop_list_free(compute_unit->tex_engine.finished_queue);
	evg_uop_list_free(compute_unit->tex_engine.fetch_queue);
	evg_uop_free(compute_unit->tex_engine.inst_buffer);
	evg_uop_list_free(compute_unit->tex_engine.load_queue);

	/* TEX Engine - structures */
	linked_list_free(compute_unit->tex_engine.pending_queue);
	linked_list_free(compute_unit->tex_engine.finished_queue);
	linked_list_free(compute_unit->tex_engine.fetch_queue);
	linked_list_free(compute_unit->tex_engine.load_queue);

	/* Compute unit */
	linked_list_free(compute_unit->wavefront_pool);
	free(compute_unit->work_groups);  /* List of mapped work-groups */
	mod_free(compute_unit->local_memory);
	free(compute_unit);
}
Пример #15
0
__inline int pqueue_extract(PQueue queue,ElmtType* data)
{
	return heap_extract(queue, data);
}
Пример #16
0
int main()

{

//	int j;

	int func;

	int value;

	char cmd[1024];

	printf("Please input the heap size : ");

	scanf("%d",&size);

	printf("\n");

	heap = build_heap(size);

	maxheap(heap);

	do{	

	    printf("1) Insert 2) Delete 3) Extract max 4) Top Value 5) Print Heap 6)Free:");

		for(func = 0; func<=0 || func > 7; sscanf(cmd,"%d",&func)){

		  scanf("%s",cmd);

		  printf("\n");

	      }

	    switch(func){

	    	

	      case 1:

	      	printf("please input new value for insert:");

		    scanf("%d ",&value);	

		    printf("\n");

	        heap_insert(heap,value);			     

		  break;	

	      

	      case 2:

		  printf("please input heap-index to delete:");

		    scanf("%d ",&value);	

		    printf("\n");	

	       heap_delete(value);

		  break;

		  

		  case 3:	

	       heap_extract();

		  break;

		  

		  case 4:	

	        heap_top(heap);

		  break;

		  

		  case 5:

		  	heap_print();

		  break;

		  

		  case 6:

		  	free(heap->array);

		  	//free(heap);

		  	size = 0;

		  	break;

		  

	    }  

	      

	}while(1);

	

	

	

	

	return 0;

}
Пример #17
0
/* XXX invariant: sch > 0 || V >= min(S in neh) */
static struct mbuf *
wf2qp_dequeue(struct dn_sch_inst *_si)
{
	/* Access scheduler instance private data */
	struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1);
	struct mbuf *m;
	struct dn_queue *q;
	struct dn_heap *sch = &si->sch_heap;
	struct dn_heap *neh = &si->ne_heap;
	struct wf2qp_queue *alg_fq;

	if (sch->elements == 0 && neh->elements == 0) {
		/* we have nothing to do. We could kill the idle heap
		 * altogether and reset V
		 */
		idle_check(si, 0x7fffffff, 1);
		si->V = 0;
		si->wsum = 0;	/* should be set already */
		return NULL;	/* quick return if nothing to do */
	}
	idle_check(si, 1, 0);	/* drain something from the idle heap */

	/* make sure at least one element is eligible, bumping V
	 * and moving entries that have become eligible.
	 * We need to repeat the first part twice, before and
	 * after extracting the candidate, or enqueue() will
	 * find the data structure in a wrong state.
	 */
  m = NULL;
  for(;;) {
	/*
	 * Compute V = max(V, min(S_i)). Remember that all elements
	 * in sch have by definition S_i <= V so if sch is not empty,
	 * V is surely the max and we must not update it. Conversely,
	 * if sch is empty we only need to look at neh.
	 * We don't need to move the queues, as it will be done at the
	 * next enqueue
	 */
	if (sch->elements == 0 && neh->elements > 0) {
		si->V = MAX64(si->V, HEAP_TOP(neh)->key);
	}
	while (neh->elements > 0 &&
		    DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) {
		q = HEAP_TOP(neh)->object;
		alg_fq = (struct wf2qp_queue *)q;
		heap_extract(neh, NULL);
		heap_insert(sch, alg_fq->F, q);
	}
	if (m) /* pkt found in previous iteration */
		break;
	/* ok we have at least one eligible pkt */
	q = HEAP_TOP(sch)->object;
	alg_fq = (struct wf2qp_queue *)q;
	m = dn_dequeue(q);
	heap_extract(sch, NULL); /* Remove queue from heap. */
	si->V += (uint64_t)(m->m_pkthdr.len) * si->inv_wsum;
	alg_fq->S = alg_fq->F;  /* Update start time. */
	if (q->mq.head == 0) {	/* not backlogged any more. */
		heap_insert(&si->idle_heap, alg_fq->F, q);
	} else {			/* Still backlogged. */
		/* Update F, store in neh or sch */
		uint64_t len = q->mq.head->m_pkthdr.len;
		alg_fq->F += len * alg_fq->inv_w;
		if (DN_KEY_LEQ(alg_fq->S, si->V)) {
			heap_insert(sch, alg_fq->F, q);
		} else {
			heap_insert(neh, alg_fq->S, q);
		}
	}
    }
	return m;
}
Пример #18
0
uint64_t pq_extract( rtems_task_argument tid, int key ) {
  return heap_extract(tid, key);
}
Пример #19
0
/*
 * 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 }; /* queue to accumulate results */

	CURVNET_SET((struct vnet *)context);

	DN_BH_WLOCK();

	/* Update number of lost(coalesced) ticks. */
	tick_lost += pending - 1;

	getmicrouptime(&t);
	/* Last tick duration (usec). */
	tick_last = (t.tv_sec - dn_cfg.prev_t.tv_sec) * 1000000 +
	(t.tv_usec - dn_cfg.prev_t.tv_usec);
	/* Last tick vs standard tick difference (usec). */
	tick_delta = (tick_last * hz - 1000000) / hz;
	/* Accumulated tick difference (usec). */
	tick_delta_sum += tick_delta;

	dn_cfg.prev_t = t;

	/*
	* 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.
	*/
	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++;
	}

	/* serve pending events, accumulate in q */
	for (;;) {
		struct dn_id *p;    /* generic parameter to handler */

		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 { /* extracted a delay line */
			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_BH_WUNLOCK();
	dn_reschedule();
	if (q.head != NULL)
		dummynet_send(q.head);
	CURVNET_RESTORE();
}