9 * There are two kinds of messages: urgent and relaxed.
11 * Urgent messages may be due for speedy transmission. The due urgent
12 * message with the highest priority is always transmitted as soon as
13 * a slot is available. This is known as `speedy transmission'.
15 * When no urgent messages are due for speedy transmission, messages
16 * (urgent or relaxed) are transmitted in a round-robin fashion. This
17 * round-robin transmission is completely independent of the speedy
20 * Each urgent message is due for speedy transmission as follows:
21 * - When it is first queued and has not yet been
22 * speedily transmitted:
23 * immediately due, with maximum priority
24 * - Following each speedy transmission:
25 * due after an interval since the previous
26 * transmission; this interval increases exponentially
27 * for each transmission
28 * with priority which decreases with later transmissions
29 * until it has been speedily transmitted a certain number of times
31 * no longer ever due; subject to round-robin transmission only.
32 * Intervals are measured in messages regardless of length.
36 * All messages are on the single relaxed queue.
37 * There is one queue for each speady retransmission; messages are on
38 * it in chronological order of dueness.
43 #include "retransmit-table.h"
45 #define RETRANSMIT_TIME_SIGNED_MAX ((~(Retransmit__Time)0) >> 1)
47 static PicInsn linefill;
49 static DLIST2_HEAD(RetransmitRelaxedNode) relaxed;
50 static Retransmit__Time elapsed;
51 static PerSpeedyTrans speedies[] = SPEEDIESINIT;
53 static void retransmit_this(const PicInsn *pi) {
58 void retransmit_start(void) {
63 nmra_encodeforpic(&n, &linefill);
65 retransmit_something();
66 retransmit_something();
67 retransmit_something();
70 void retransmit_something(void) {
72 RetransmitUrgentNode *urg;
73 RetransmitRelaxedNode *rlx;
76 for (ix=0, spd=speedies;
81 if (elapsed - urg->u.when > RETRANSMIT_TIME_SIGNED_MAX) continue;
83 /* found one to transmit: */
84 DLIST2_REMOVE(spd->queue,urg,u.queue);
85 if (++ix < SPEEDYCOUNT) {
87 urg->u.when= elapsed + spd->interval;
89 DLIST2_APPEND(spd->queue,urg,u.queue);
93 retransmit_this(&urg->pi);
99 DLIST2_REMOVE(relaxed,rlx,rr);
100 DLIST2_APPEND(relaxed,rlx,rr);
101 retransmit_this(&rlx->pi);
105 serial_transmit(&linefill);
108 void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, Nmra *n) {
109 if (n) { nmra_addchecksum(n); nmra_encodeforpic(n, &rn->pi); }
110 DLIST2_PREPEND(relaxed,rn,rr);
112 void retransmit_relaxed_requeue(RetransmitRelaxedNode *rn, Nmra *n) {
113 retransmit_relaxed_cancel(rn);
114 retransmit_relaxed_queue(rn, n);
116 void retransmit_relaxed_cancel(RetransmitRelaxedNode *rlx) {
117 DLIST2_REMOVE(relaxed,rlx,rr);
120 void retransmit_urgent_queue(RetransmitUrgentNode *urg, Nmra *n) {
121 retransmit_relaxed_queue(&urg->u.relaxed, n);
123 urg->u.when= elapsed;
124 DLIST2_APPEND(speedies[0].queue,urg,u.queue);
126 void retransmit_urgent_queue_relaxed(RetransmitUrgentNode *urg, Nmra *n){
127 retransmit_relaxed_queue(&urg->u.relaxed, n);
129 urg->u.when= elapsed;
131 void retransmit_urgent_requeue(RetransmitUrgentNode *rn, Nmra *n) {
132 retransmit_urgent_cancel(rn);
133 retransmit_urgent_queue(rn, n);
135 void retransmit_urgent_cancel(RetransmitUrgentNode *urg) {
137 DLIST2_REMOVE(speedies[urg->u.ix].queue,urg,u.queue);
138 retransmit_relaxed_cancel(&urg->u.relaxed);