void retransmit_start(void);
void retransmit_something(void);
-void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, Nmra *n);
-void retransmit_relaxed_requeue(RetransmitRelaxedNode *rn, Nmra *n);
-void retransmit_relaxed_cancel(RetransmitRelaxedNode *rn);
-
void retransmit_urgent_queue(RetransmitUrgentNode *rn, Nmra *n);
void retransmit_urgent_queue_relaxed(RetransmitUrgentNode *urg, Nmra *n);
void retransmit_urgent_requeue(RetransmitUrgentNode *rn, Nmra *n);
void retransmit_urgent_cancel(RetransmitUrgentNode *rn);
- /* ... NB: these are NOT idempotent. Use _requeue it's queued;
- * _requeue is just _cancel followed by queue. */
+void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, Nmra *n);
+void retransmit_relaxed_cancel(RetransmitRelaxedNode *rn);
+
+ /* ... NB: these are NOT idempotent and NOT interchangeable. Use
+ * urgent_requeue if it's queued and has changed and must get a new
+ * quota of urgency; _requeue is just _cancel followed by queue. */
/*---------- features, filled in by record, used by features.c ----------*/
*/
/*
* Implementation:
- * All messages are on the single relaxed queue.
+ * All messages are on one of the relaxed queues; urgent messages
+ * are on the relaxed[0] queue and messages which are explicitly
+ * relaxed are on the relaxed[1] queue. This gives the previously-
+ * urgent messages 50% of the bandwidth.
* There is one queue for each speady retransmission; messages are on
* it in chronological order of dueness.
*/
static PicInsn linefill;
-static DLIST2_HEAD(RetransmitRelaxedNode) relaxed;
+static DLIST2_HEAD(RetransmitRelaxedNode) relaxed[2];
+static int last_relaxed_qn;
static Retransmit__Time elapsed;
static PerSpeedyTrans speedies[] = SPEEDIESINIT;
return;
}
- rlx= relaxed.head;
- if (rlx) {
- DLIST2_REMOVE(relaxed,rlx,rr);
- DLIST2_APPEND(relaxed,rlx,rr);
+ for (ix=0; ix<2; ix++) {
+ int qn= last_relaxed_qn ^ ix ^ 1;
+ rlx= relaxed[qn].head;
+ if (!rlx) continue;
+
+ DLIST2_REMOVE(relaxed[qn],rlx,rr);
+ DLIST2_APPEND(relaxed[qn],rlx,rr);
retransmit_this(&rlx->pi);
+ last_relaxed_qn= qn;
return;
}
serial_transmit(&linefill);
}
-void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, Nmra *n) {
+static void relaxed_queue(int qn, RetransmitRelaxedNode *rn, Nmra *n) {
if (n) { nmra_addchecksum(n); nmra_encodeforpic(n, &rn->pi); }
- DLIST2_PREPEND(relaxed,rn,rr);
+ DLIST2_PREPEND(relaxed[qn],rn,rr);
+}
+static void relaxed_cancel(int qn, RetransmitRelaxedNode *rlx) {
+ DLIST2_REMOVE(relaxed[qn],rlx,rr);
}
-void retransmit_relaxed_requeue(RetransmitRelaxedNode *rn, Nmra *n) {
- retransmit_relaxed_cancel(rn);
- retransmit_relaxed_queue(rn, n);
+
+void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, Nmra *n) {
+ relaxed_queue(1,rn,n);
}
void retransmit_relaxed_cancel(RetransmitRelaxedNode *rlx) {
- DLIST2_REMOVE(relaxed,rlx,rr);
+ relaxed_cancel(1,rlx);
}
void retransmit_urgent_queue(RetransmitUrgentNode *urg, Nmra *n) {
- retransmit_relaxed_queue(&urg->u.relaxed, n);
+ relaxed_queue(0, &urg->u.relaxed, n);
urg->u.ix= 0;
urg->u.when= elapsed;
DLIST2_APPEND(speedies[0].queue,urg,u.queue);
}
void retransmit_urgent_queue_relaxed(RetransmitUrgentNode *urg, Nmra *n){
- retransmit_relaxed_queue(&urg->u.relaxed, n);
+ relaxed_queue(0, &urg->u.relaxed, n);
urg->u.ix= -1;
urg->u.when= elapsed;
}
void retransmit_urgent_cancel(RetransmitUrgentNode *urg) {
if (urg->u.ix >= 0)
DLIST2_REMOVE(speedies[urg->u.ix].queue,urg,u.queue);
- retransmit_relaxed_cancel(&urg->u.relaxed);
+ relaxed_cancel(0, &urg->u.relaxed);
}