chiark / gitweb /
new queues, just a few things to do now
authorian <ian>
Fri, 4 Apr 2008 20:09:17 +0000 (20:09 +0000)
committerian <ian>
Fri, 4 Apr 2008 20:09:17 +0000 (20:09 +0000)
hostside/movpos.c

index b1c505f34db4f8966b2348cd22ea5f06b71d80b4..04cb96e0723af24f4164aeb6979f0106ae44813b 100644 (file)
@@ -48,19 +48,26 @@ typedef struct MovPosChangeDetails {
  *     changing      line         that
  */
 
-typedef unsigned Slot;
-
-typedef struct PointReq {     /* Allocated Reserved  Enqueued   Deleting  */
-  ChangeHeader h;
-  int n_motions;              /*  alloc_..  alloc_..  n_motions  0        */
-  PointMotion motions[];      /*  undef     defined   defined    defined  */ 
-}
-
-typedef struct PointMotion {  /* Allocated Reserved  Enqueued   Deleting  */
-  Motion m;        /*      .i:    undef     0         non-0      PT_DEL   */
-                   /*   .posn:    undef     undef     defined    any      */
-  Slot deadline;   /*             undef     relative  absolute   any      */
-} PointReq;        /* in plan?    no        yes       yes        removing */
+typedef unsigned PtSlot;
+typedef int PtSlotSigned;
+
+typedef struct {             /* Allocated Reserved  Confirmed               */
+                   /* in queue?  absent    reserved  confirmed              */
+  ChangeHeader h;                                                these two  */
+  Slot deadline;   /*            ~0        relative  absolute  <- `statedet' */
+  int n_motions;   /*            alloc'd   alloc'd   undone       fields    */
+  Motion motions[];/*   [0].i:   0         0         non-0     <- indicate  */
+                   /*  [..].i:   undef     undef     non-0        state     */
+                   /*   .posn:   undef     undef     defined                */
+} PointReq;
+  /* We abbreviate these states as   A R C
+   * There are also intermediate states where the req's
+   *  statedet fields do not agree with the queue it's on.
+   *  We write these as, for example,
+   *      AR   to mean  statedet says Allocated, but queued on pt_reserved
+   *      A?   to mean  statedet says Allocated, but may be queued
+   *  etc.  They are only allowed while we are in a pt_... method function.
+   */
 
 /* We increment cslot when we issue a POINT command to the PIC.
  * deadline represents the latest allowable value of cslot
@@ -68,124 +75,130 @@ typedef struct PointMotion {  /* Allocated Reserved  Enqueued   Deleting  */
 
 #define CDU_RECHARGE   250 /*ms*/
 #define POINT_MOVEMENT  50 /*ms*/
-#define PT_MAX_PLAN     15
 
-static Slot pt_cslot;
-static int pt_planlen;
-static PointMotion *pt_plan[PT_MAX_PLAN];
+#define PT_MAX_QUEUE  15
 
-#define PT_DEL ((const MovFeatInfo*)info_segments) /* some random struct */
+static PtSlot pt_cslot;
 
-static SomeChange pt_allocate(int alloc_motions) {
-  PointReq= *p;
+/*
+ * We maintain two queues, one for reserved one for actually confirmed
+ *  requests where we know what we're doing.
+ */
 
-  p= mmalloc(sizeof(*p) + alloc_motions * sizeof(p->motions[0]));
-  p->n_motions= alloc_motions;
-  return (SomeChange*)p;
-}
+todo
+ actually fire points: use item, and remove it, etc.
+ write check routine
 
-static pt_maxdelay_reldeadline(int maxdelay_ms) {
+typedef struct {
+  int n;
+  PointReq *l[PT_MAX_QUEUE];
+} PointQueue;
+
+static PointQueue pt_confirmed, pt_reserved;
+
+#define PT_DEL ((const MovFeatInfo*)info_segments) /* some random struct */
+
+static pt__maxdelay_reldeadline(int maxdelay_ms) {
   return (maxdelay_ms - POINT_MOVEMENT + CDU_RECHARGE) / CDU_RECHARGE;
 }
 
-static ErrorCode pt_insertreq(PointReq *pt) {
-  int i;
-  
-  int n_add= pt->n_motions;
-  if (n_add==0) return 0;
-
-  int new_planlen= pt_planlen + new->n_motions;
-  if (new_planlen > PT_MAX_PLAN) return EC_BufferFull;
-
-  insat= pt_planlen;
-  new_reldeadline= pt_motion_reldeadline(pt->motions[0].deadline);
-  for (;;) {
-    if (insat<=0) break;
-    delaying_reldeadline= pt_motion_reldeadline(pt_plan[insat]->deadline);
-    if (new_reldeadline >= delaying_reldeadline) break;
-    int copyto= insat + n_add;
-    if (copyto > new_reldeadline) return EC_Points;
-    insat--;
-  }
-  if (insat + n_add - 1 > new_reldeadline)
-    return EC_Points;
-
-  int copyto= insat + n_add;
-  memmove(&pt_plan[copyto], &pt_plan[insat], sizeof(pt_plan[0]) * n_add);
-  for (i=0; i<n_add; i++)
-    pt_plan[insat+i]= &pt->motions[i];
+static void pt__queue_remove_index(PointQueue *q, int index) {
+  q->n--;
+  memmove(&q->l[index], &q->l[index+1], sizeof(q->l[0]) * (q->n - index));
+}
 
-  while (insat>0 &&
-        
-        < (moving_reldeadline= 
-    
+static void pt__req_compar(const void *av, const void *bv) {
+  PointQueue *const *a= av;
+  PointQueue *const *b= av;
+  return (PtSlotSigned)((*b)->deadline - (*a)->deadline);
+}
 
-       insat[-1]
-    int this_rel
+static void pt__queue_remove_item(PointQueue *q, PointReq *r) {
+  PointQueue **entry;
+  entry= bsearch(r, q->l, q->n, sizeof(q->l[0]), pt__req_compar);
+  assert(entry);
+  pt__queue_remove_index(q, entry - q->l);
+}
 
-static ErrorCode pt_reserve(SomeChange *chg, Segment *move, int maxdelay_ms) {
-  PointReq *p= (PointReq*)chg;
-  PointMotion *m;
-  int mi;
-  Slot deadline= pt_reldeadline(maxdelay_ms);
-  
-  for (mi=0, m=p->motions; mi < p->n_motions; mi++, m++) {
-    m->m.i= 0;
-    m->deadline= deadline;
+static void pt__dequeue(PointReq *r) { /* X->XA */
+  if (r->motions[0].i) {
+    pt__queue_remove_item(&pt_confirmed, r);
+  } else if (~r->deadline) {
+    pt__queue_remove_item(&pt_reserved, r);
   }
-  return pt_insertreq(p);
 }
 
-static int point__putbefore(PointReq *new, PointReq *existing) {
-  return new->startby < existing->startby;
+static void pt_destroy(SomeChange *chg) { /* X->XA and then free it */
+  PointReq *r= (PointReq*)chg;
+  pt__dequeue(r);
+  free(r);
 }
 
-static ErrorCode point__enqueue(PointReq *p, int count, int maxdelay_ms,
-                               Slot minrelslot) {
-  Slot relslot;
-  PointReq *ref;
-
-  relslot= (maxdelay_ms - POINT_MOVEMENT + CDU_RECHARGE) / CDU_RECHARGE
-         - count;
-  if (relslot < minrelslot) return EC_Point;
+static void pt__mark_as_allocated(PointReq *r) { /* AX->X */
+  /* Sets statedet fields for Allocated */
+  r->deadline= ~(PtSlot)0;
+  r->motions[0].i=0;
+}
 
-  p->startby= cslot + relslot;
+static ErrorCode pt__enqueue(PointQueue *q, PointReq *r) { /* XA -> X */
+  ErrorCode ec;              /* ... where X is R or C and corresponds to q */
+                             /* or on error,   XA -> A */
   
-  if (!queue.tail || !point__putbefore(p, queue.tail)) {
-    DLIST2_APPEND(queue,p,qe);
-    return;
+  if (q->n == PT_MAX_QUEUE) {
+    return EC_BufferFull;
   }
-  if (point_putbefore(p, lastinsert)) {
-    for (ref=lastinsert;
-        ref->qe.back && point_putbefore(p, ref);
-        ref= ref->qe.back);
-    DLIST2_INSERT_BEFORE(queue,p,qe,ref);
-  } else {
-    for (ref=lastinsert;
-        ref->qe.next && !point_putbefore(p, ref);
-        );
-    DLIST2_INSERT_AFTER(queue,p,qe,ref);
-    
-    
-
-  if (!lastinsert) 
-}
 
-static ErrorCode point_reserve(SomeChange *chg, Segment *move,
-                              int maxdelay_ms) {
-  
+  for (insat= q->n;
+       insat>0 && CLOCK_COMPARE(r->deadline, <, q->l[insat-1]->deadline);
+       insat--)
+    q->l[insat]= q->l[insat-1];
+  q->l[insat]= r;
+  q->n++;
 
-    cslot + maxdelay_ms / POINT_EVERY_MS  this is not right;
-  
+  return pt_check();
+  /* if this fails, indep machinery calls pt_destroy which dequeues */
+}
 
-  ErrorCode (*request)(SomeChange*, Segment *move,
-                      int n_motions, const Motion*, int maxdelay_ms);
-  void (*destroy)(SomeChange*);
+static SomeChange pt_allocate(int alloc_motions) {
+  PointReq= *r;
 
+  r= mmalloc(sizeof(*r) + alloc_motions * sizeof(r->motions[0]));
+  r->deadline= ~(PtSlot)0;
+  r->n_motions= alloc_motions;
+  r->motions[0].i= 0;
+  return (SomeChange*)r;
+}
 
-convert incoming latest's into queue lengths as simple counts
-maintain latest count number for each 
+static ErrorCode pt_reserve(SomeChange *chg, Segment *move, int maxdelay_ms) {
+  PointReq *r= (PointReq*)chg;
+  r->deadline= pt_reldeadline(maxdelay_ms);
+  return pt_queue_add(&pt_reserved, r);
+}
 
+static ErrorCode pt_request(SomeChange *chg, Segment *move,
+                           int n_motions, const Motion *motions,
+                           int maxdelay_ms) {
+                                           /* [AR]->C; on error: [AR]->X */
+  PointReq *r= (PointReq*)chg;
+  PtSlot newdeadline;
+  int allow_failure;
+
+  assert(n_motions <= r->n_motions);
+  newdeadline= pt_reldeadline(maxdelay_ms) + cslot;
+  allow_failure= newdeadline < r->deadline;
+
+  /* state [AR] */
+  pt__dequeue(r);
+  /* state [AR]A */
+  assert(n_motions>0 && motions[0].i);
+  memcpy(r->motions, motions, sizeof(r->motions[0])*n_motions);
+  r->n_motions= n_motions;
+  r->deadline= newdeadline + pt_cslot;
+  /* state CA */
+  ec= pt__enqueue(&pt_confirmed, r);
+  assert(allow_failure || !ec);
+  return ec;
+}
 
 
 /*---------- method-independent machinery ----------*/
@@ -257,7 +270,7 @@ movpos_requestchange(Segment *back, Segment *move, *Segment *fwd,
     (*req_io)->on_done=   on_done;
     (*req_io)->u=         u;
   } else {
-    if (n_motions > (*req_io)->move->i->n_movfeats) { ec= EC_Invalid; return; }
+    if (move != (*req_io)->move) { ec= EC_Invalid; return; }
   }
 
   ec= mi->request((SomeChange*)*req_io, move, n_motions, motions, maxdelay_ms);