// SPDX-License-Identifier: GPL-2.0-or-later /* SCTP kernel implementation * (C) Copyright Red Hat Inc. 2017 * * This file is part of the SCTP kernel implementation * * These functions manipulate sctp stream queue/scheduling. * * Please send any bug reports or fixes you make to the * email addresched(es): * lksctp developers <linux-sctp@vger.kernel.org> * * Written or modified by: * Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
*/
staticstruct sctp_stream_priorities *sctp_sched_prio_get_head( struct sctp_stream *stream, int prio, gfp_t gfp)
{ struct sctp_stream_priorities *p; int i;
/* Look into scheduled priorities first, as they are sorted and * we can find it fast IF it's scheduled.
*/
list_for_each_entry(p, &stream->prio_list, prio_sched) { if (p->prio == prio) return sctp_sched_prio_head_get(p); if (p->prio > prio) break;
}
/* No luck. So we search on all streams now. */ for (i = 0; i < stream->outcnt; i++) { if (!SCTP_SO(stream, i)->ext) continue;
p = SCTP_SO(stream, i)->ext->prio_head; if (!p) /* Means all other streams won't be initialized * as well.
*/ break; if (p->prio == prio) return sctp_sched_prio_head_get(p);
}
/* If not even there, allocate a new one. */ return sctp_sched_prio_new_head(stream, prio, gfp);
}
if (!list_empty(&soute->prio_list)) { struct sctp_stream_priorities *prio_head = soute->prio_head;
/* Scheduled */
scheduled = true;
if (prio_head->next == soute) /* Try to move to the next stream */
sctp_sched_prio_next_stream(prio_head);
list_del_init(&soute->prio_list);
/* Also unsched the priority if this was the last stream */ if (list_empty(&prio_head->active)) {
list_del_init(&prio_head->prio_sched); /* If there is no stream left, clear next */
prio_head->next = NULL;
}
}
/* Nothing to do if already scheduled */ if (!list_empty(&soute->prio_list)) return;
/* Schedule the stream. If there is a next, we schedule the new * one before it, so it's the last in round robin order. * If there isn't, we also have to schedule the priority.
*/ if (prio_head->next) {
list_add(&soute->prio_list, prio_head->next->prio_list.prev); return;
}
/* Bail out quickly if queue is empty */ if (list_empty(&q->out_chunk_list)) goto out;
/* Find which chunk is next. It's easy, it's either the current * one or the first chunk on the next active stream.
*/ if (stream->out_curr) {
soute = stream->out_curr->ext;
} else {
prio = list_entry(stream->prio_list.next, struct sctp_stream_priorities, prio_sched);
soute = prio->next;
}
ch = list_entry(soute->outq.next, struct sctp_chunk, stream_list);
sctp_sched_dequeue_common(q, ch);
/* Last chunk on that msg, move to the next stream on * this priority.
*/
sid = sctp_chunk_stream_no(ch);
soute = SCTP_SO(&q->asoc->stream, sid)->ext;
prio = soute->prio_head;
sctp_sched_prio_next_stream(prio);
if (list_empty(&soute->outq))
sctp_sched_prio_unsched(soute);
}
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 und die Messung sind noch experimentell.