chiark / gitweb /
Give relaxed xmissions of urgent messages >=50% share
authorian <ian>
Thu, 26 Jun 2008 16:19:52 +0000 (16:19 +0000)
committerian <ian>
Thu, 26 Jun 2008 16:19:52 +0000 (16:19 +0000)
hostside/realtime.h
hostside/retransmit.c

index 419f1436fa6814cca9621ecd2861b70b8e8741e8..7dc083c69fdfe6557b8c02a5f3012ee67fe2cf9e 100644 (file)
@@ -55,17 +55,17 @@ union RetransmitUrgentNode {
 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 ----------*/
 
index ab3546324a06c76e06c2127018d3316957b83f99..0f404c09d01bf99a6b630ce16af9cdef2761bb89 100644 (file)
  */
 /*
  * 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.
  */
@@ -46,7 +49,8 @@
 
 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;
 
@@ -94,37 +98,44 @@ void retransmit_something(void) {
     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;
 }
@@ -135,7 +146,7 @@ void retransmit_urgent_requeue(RetransmitUrgentNode *rn, Nmra *n) {
 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);
 }