/*
 * Packets are dequeued only from the highest priority queue.
 * The function ffs() return the lowest bit in the bitmap that rapresent
 * the array index (-1) which contains the pointer to the highest priority
 * queue.
 * After the dequeue, if this queue become empty, it is index is removed
 * from the bitmap.
 * Scheduler is idle if the bitmap is empty
 *
 * NOTE: highest priority is 0, lowest is sched->max_prio_q
 */
static struct mbuf *
prio_dequeue(struct dn_sch_inst *_si)
{
	struct prio_si *si = (struct prio_si *)(_si + 1);
	struct mbuf *m;
	struct dn_queue *q;
	int prio;

	if (si->bitmap == 0) /* scheduler idle */
		return NULL;

	prio = ffs(si->bitmap) - 1;

	/* Take the highest priority queue in the scheduler */
	q = si->q_array[prio];
	// assert(q)

	m = dn_dequeue(q);
	if (q->mq.head == NULL) {
		/* Queue is now empty, remove from scheduler
		 * and mark it
		 */
		si->q_array[prio] = NULL;
		__clear_bit(prio, &si->bitmap);
	}
	return m;
}
Exemple #2
0
static struct mbuf *
rr_dequeue(struct dn_sch_inst *_si)
{
	/* Access scheduler instance private data */
	struct rr_si *si = (struct rr_si *)(_si + 1);
	struct rr_queue *rrq;
	uint64_t len;

	while ( (rrq = si->head) ) {
		struct mbuf *m = rrq->q.mq.head;
		if ( m == NULL) {
			/* empty queue, remove from list */
			rr_remove_head(si);
			continue;
		}
		len = m->m_pkthdr.len;

		if (len > rrq->credit) {
			/* Packet too big */
			rrq->credit += rrq->quantum;
			/* Try next queue */
			next_pointer(si);
		} else {
			rrq->credit -= len;
			return dn_dequeue(&rrq->q);
		}
	}

	/* no packet to dequeue*/
	return NULL;
}
/* 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;
}
static struct mbuf *
fifo_dequeue(struct dn_sch_inst *si)
{
	return dn_dequeue((struct dn_queue *)(si + 1));
}