コード例 #1
0
/*
 * For any block B_i in the queue, we know that the bsize for
 * that block is at least (f->length - B_i->col).
 *
 * If (f->length - B_0->col > f->max_width) then we can set B_0's
 * bsize to infinity (PP_MAX_BSIZE), update the csize of the head
 * token, and remove B_0 from the queue. The head token is ready to be
 * printed at this point (since its csize, bsize and fsize fields are
 * known).
 */
static void flush_wide_blocks(formatter_t *f) {
  pp_block_t *b;
  pp_open_token_t *tk, *head;

  while (!block_queue_is_empty(&f->block_queue)) {
    b = first_block(&f->block_queue);
    assert(b->col <= f->length);
    if (f->length - b->col <= f->max_width) break;
    /*
     * b has bsize > max_width: set its bsize to MAX
     * then remove it from the block queue
     */
    tk = b->token;
    tk->bsize = PP_MAX_BSIZE;
    head = f->head_token;
    if (head != NULL) {
      // update csize and fsize of the head token
      head->csize = PP_MAX_BSIZE;
      if (head->fsize == 0) {
        head->fsize = PP_MAX_BSIZE;
      }
    }
    // print all queued tokens, until tk
    flush_tokens(f, tag_open(tk));

    // tk becomes the head token
    assert(ptr_queue_first(&f->token_queue) == tag_open(tk));
    f->head_token = tk;
    if (f->nclosed == f->queue_size) {
      f->nclosed --;
    }

    pop_first_block(&f->block_queue);
    f->queue_size --;
  }
}
コード例 #2
0
ファイル: qio.c プロジェクト: mtaufen/akaros
/* Helper and back-end for __qbread: extracts and returns a list of blocks
 * containing up to len bytes.  It may contain less than len even if q has more
 * data.
 *
 * Returns a code interpreted by __qbread, and the returned blist in ret. */
static int __try_qbread(struct queue *q, size_t len, int qio_flags,
                        struct block **real_ret, struct block *spare)
{
	struct block *ret, *ret_last, *first;
	size_t blen;

	if (qio_flags & QIO_CAN_ERR_SLEEP) {
		if (!qwait_and_ilock(q, qio_flags)) {
			spin_unlock_irqsave(&q->lock);
			return QBR_FAIL;
		}
		/* we qwaited and still hold the lock, so the q is not empty */
		first = q->bfirst;
	} else {
		spin_lock_irqsave(&q->lock);
		first = q->bfirst;
		if (!first) {
			spin_unlock_irqsave(&q->lock);
			return QBR_FAIL;
		}
	}
	blen = BLEN(first);
	if ((q->state & Qcoalesce) && (blen == 0)) {
		freeb(pop_first_block(q));
		spin_unlock_irqsave(&q->lock);
		/* Need to retry to make sure we have a first block */
		return QBR_AGAIN;
	}
	/* Qmsg is a bit weird.  The old 9ns code seemed to yank the entire block,
	 * regardless of len.  We'll do the same, and just return the minimum: the
	 * first block.  I'd be happy to remove this. */
	if (q->state & Qmsg) {
		ret = pop_first_block(q);
		goto out_ok;
	}
	/* Let's get at least something first - makes the code easier.  This way,
	 * we'll only ever split the block once. */
	if (blen <= len) {
		ret = pop_first_block(q);
		len -= blen;
	} else {
		/* need to split the block.  we won't actually take the first block out
		 * of the queue - we're just extracting a little bit. */
		if (!spare) {
			/* We have nothing and need a spare block.  Retry! */
			spin_unlock_irqsave(&q->lock);
			return QBR_SPARE;
		}
		copy_from_first_block(q, spare, len);
		ret = spare;
		goto out_ok;
	}
	/* At this point, we just grabbed the first block.  We can try to grab some
	 * more, up to len (if they want). */
	if (qio_flags & QIO_JUST_ONE_BLOCK)
		goto out_ok;
	ret_last = ret;
	while (q->bfirst && (len > 0)) {
		blen = BLEN(q->bfirst);
		if ((q->state & Qcoalesce) && (blen == 0)) {
			/* remove the intermediate 0 blocks */
			freeb(pop_first_block(q));
			continue;
		}
		if (blen > len) {
			/* We could try to split the block, but that's a huge pain.  For
			 * instance, we might need to move the main body of b into an
			 * extra_data of ret_last.  lots of ways for that to fail, and lots
			 * of cases to consider.  Easier to just bail out.  This is why I
			 * did the first block above: we don't need to worry about this. */
			 break;
		}
		ret_last->next = pop_first_block(q);
		ret_last = ret_last->next;
		len -= blen;
	}
out_ok:
	qwakeup_iunlock(q);
	*real_ret = ret;
	return QBR_OK;
}