chiark / gitweb /
realtime: movpos: need to cope with reentrant calls to method_change_done, since...
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 9 Jan 2011 17:44:53 +0000 (17:44 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 9 Jan 2011 17:44:53 +0000 (17:44 +0000)
hostside/movpos.c

index bfb29a4fc9eb88862651e4ea8c4e22d1bfd36433..4bbc7f7f78c579f16c2d2919a1714d28a752fe18 100644 (file)
@@ -18,6 +18,7 @@ typedef struct MovPosChange {
   Segment *move;
   /* everything beyond here is private for indep */
   MovPosComb actual, target;
+  int refcount;
   int n_changes;
   Change *changes[];
 } Indep;
@@ -35,9 +36,9 @@ static void method_change_done(Method *m, Change *chg);
    * has been done.  The method-independent code will take care of
    * updating move->movposcomb. etc.
    *
-   * REENTRANCY: must NOT be called from within a call to the method's
-   * execute() (and of course cannot legally be called from within
-   * prepare, consider, check or dispose).
+   * REENTRANCY: May be called from within a call to the method's
+   * execute().  Of course cannot legally be called from within
+   * prepare, consider, check or dispose.
    */
 
 
@@ -604,7 +605,6 @@ typedef struct NomoveChange {
 
 typedef struct {
   Method m;
-  unsigned eventqueued:1;
   NomoveChange *queuehead; /* contains confirmations only */
 } NomoveMethod;
 
@@ -646,10 +646,8 @@ static void nomove_remove(Method *mm, Change *remvchg) {
 
 static ErrorCode nomove_check(Method *mm) { return 0; }
 
-static void *nomove_execute_now(oop_source *source, struct timeval tv,
-                               void *meth_v) {
-  NomoveMethod *meth= meth_v;
-  meth->eventqueued= 0;
+static void nomove_execute(Method *mm) {
+  NomoveMethod *meth= (void*)mm;
   NomoveChange *done;
 
   while ((done= meth->queuehead)) {
@@ -661,15 +659,6 @@ static void *nomove_execute_now(oop_source *source, struct timeval tv,
     DLIST1_REMOVE(meth->queuehead, done, inqueue);
     nomove_dispose(&meth->m, &done->h);
   }
-  return OOP_CONTINUE;
-}
-
-static void nomove_execute(Method *mm) {
-  NomoveMethod *meth= (void*)mm;
-  if (!meth->eventqueued) {
-    meth->eventqueued= 1;
-    events->on_time(events, OOP_TIME_NOW, nomove_execute_now, meth);
-  }
 }
 
 static Method nomove_method= {
@@ -731,7 +720,8 @@ static void method_change_done(Method *m, Change *chg) {
     return;
   }
 
-  indep_indep_done(indep);
+  if (!indep->refcount)
+    indep_indep_done(indep);
 }
 
 static void indep_indep_done(Indep *indep) {
@@ -853,6 +843,7 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target,
     indep->actual= startpoint;
     indep->target= target;
     indep->n_changes= n_meths;
+    indep->refcount= 0;
     memset(indep->changes, 0, sizeof(Change*) * n_meths);
   }
   DPRINTF2("\n");
@@ -1111,9 +1102,12 @@ ErrorCode movpos_change(Segment *move, MovPosComb target,
   move->motion= inst;
   move->moving= 1;
 
+  inst->refcount++; /* prevents method_change_done from destroying it */
+
   ouposn_moving(inst);
   indep_check_execute();
 
+  inst->refcount--;
   if (!inst->n_changes)
     /* oh! */
     indep_indep_done(inst);