static int queue_oos_msg()

in ncrx/libncrx.c [468:529]


static int queue_oos_msg(struct ncrx_msg *tmsg, struct ncrx *ncrx)
{
	struct ncrx_slot *slot;
	struct ncrx_msg *msg, *nmsg, *first;

	msg = copy_msg(tmsg);
	if (!msg)
		return -1;

	msg_list_append(msg, &ncrx->oos_list);

	/*
	 * Shifted left automatically on each new msg.  Set oos and see if
	 * there have been too many oos among the last 32 messages.
	 */
	ncrx->oos_history |= 1;
	if ((signed)hweight32(ncrx->oos_history) < ncrx->p.oos_thr) {
		/* nope, handle oos overflow and handle */
		if (ncrx->oos_list.nr > NCRX_OOS_MAX) {
			msg = msg_list_pop(&ncrx->oos_list);
			if (msg) {
				msg->oos = 1;
				msg_list_append(msg, &ncrx->retired_list);
			}
		}
		return 0;
	}

	/*
	 * The current sequence stream seems no good.  Let's reset by
	 * retiring all pending, picking the oos msg with the lowest seq,
	 * queueing it to reset the seq and then queueing all other oos
	 * msgs.  If a msg is still oos after reset, just retire it.
	 */
	while (ncrx->tail != ncrx->head)
		retire_tail(ncrx);

	ncrx->head_seq = 0;
	ncrx->acked_seq = UINT64_MAX;

	first = node_to_msg(ncrx->oos_list.head.next);
	msg_list_for_each(msg, nmsg, &ncrx->oos_list)
		first = msg->seq < first->seq ? msg : first;

	msg_list_del(first, &ncrx->oos_list);
	slot = get_seq_slot(first, ncrx);
	slot->msg = first;
	slot_maybe_complete(slot);

	while ((msg = msg_list_pop(&ncrx->oos_list))) {
		slot = get_seq_slot(msg, ncrx);
		if (slot) {
			slot->msg = msg;
			slot_maybe_complete(slot);
		} else {
			msg->oos = 1;
			msg_list_append(msg, &ncrx->retired_list);
		}
	}

	return 0;
}