now = jiffies; /* Check for a potential stall */ if (time_after_eq(now, dql->last_reap + stall_thrs)) { unsignedlong hist_head, t, start, end;
/* We are trying to detect a period of at least @stall_thrs * jiffies without any Tx completions, but during first half * of which some Tx was posted.
*/
dqs_again:
hist_head = READ_ONCE(dql->history_head); /* pairs with smp_wmb() in dql_queued() */
smp_rmb();
/* Get the previous entry in the ring buffer, which is the * oldest sample.
*/
start = (hist_head - DQL_HIST_LEN + 1) * BITS_PER_LONG;
/* Advance start to continue from the last reap time */ if (time_before(start, dql->last_reap + 1))
start = dql->last_reap + 1;
/* Newest sample we should have already seen a completion for */
end = hist_head * BITS_PER_LONG + (BITS_PER_LONG - 1);
/* Shrink the search space to [start, (now - start_thrs/2)] if * `end` is beyond the stall zone
*/ if (time_before(now, end + stall_thrs / 2))
end = now - stall_thrs / 2;
/* Search for the queued time in [t, end] */ for (t = start; time_before_eq(t, end); t++) if (test_bit(t % (DQL_HIST_LEN * BITS_PER_LONG),
dql->history)) break;
/* Variable t contains the time of the queue */ if (!time_before_eq(t, end)) goto no_stall;
/* The ring buffer was modified in the meantime, retry */ if (hist_head != READ_ONCE(dql->history_head)) goto dqs_again;
dql->stall_cnt++;
dql->stall_max = max_t(unsignedshort, dql->stall_max, now - t);
/* Records completed count and recalculates the queue limit */ void dql_completed(struct dql *dql, unsignedint count)
{ unsignedint inprogress, prev_inprogress, limit; unsignedint ovlimit, completed, num_queued; unsignedshort stall_thrs; bool all_prev_completed;
num_queued = READ_ONCE(dql->num_queued); /* Read stall_thrs in advance since it belongs to the same (first) * cache line as ->num_queued. This way, dql_check_stall() does not * need to touch the first cache line again later, reducing the window * of possible false sharing.
*/
stall_thrs = READ_ONCE(dql->stall_thrs);
/* Can't complete more than what's in queue */
BUG_ON(count > num_queued - dql->num_completed);
if ((ovlimit && !inprogress) ||
(dql->prev_ovlimit && all_prev_completed)) { /* * Queue considered starved if: * - The queue was over-limit in the last interval, * and there is no more data in the queue. * OR * - The queue was over-limit in the previous interval and * when enqueuing it was possible that all queued data * had been consumed. This covers the case when queue * may have becomes starved between completion processing * running and next time enqueue was scheduled. * * When queue is starved increase the limit by the amount * of bytes both sent and completed in the last interval, * plus any previous over-limit.
*/
limit += POSDIFF(completed, dql->prev_num_queued) +
dql->prev_ovlimit;
dql->slack_start_time = jiffies;
dql->lowest_slack = UINT_MAX;
} elseif (inprogress && prev_inprogress && !all_prev_completed) { /* * Queue was not starved, check if the limit can be decreased. * A decrease is only considered if the queue has been busy in * the whole interval (the check above). * * If there is slack, the amount of excess data queued above * the amount needed to prevent starvation, the queue limit * can be decreased. To avoid hysteresis we consider the * minimum amount of slack found over several iterations of the * completion routine.
*/ unsignedint slack, slack_last_objs;
/* * Slack is the maximum of * - The queue limit plus previous over-limit minus twice * the number of objects completed. Note that two times * number of completed bytes is a basis for an upper bound * of the limit. * - Portion of objects in the last queuing operation that * was not part of non-zero previous over-limit. That is * "round down" by non-overlimit portion of the last * queueing operation.
*/
slack = POSDIFF(limit + dql->prev_ovlimit,
2 * (completed - dql->num_completed));
slack_last_objs = dql->prev_ovlimit ?
POSDIFF(dql->prev_last_obj_cnt, dql->prev_ovlimit) : 0;
slack = max(slack, slack_last_objs);
if (slack < dql->lowest_slack)
dql->lowest_slack = slack;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.