Fix timing bug in inter-thread communications. This bug occurs when
authorChris Hanson <org/chris-hanson/cph>
Fri, 3 Nov 1995 01:22:21 +0000 (01:22 +0000)
committerChris Hanson <org/chris-hanson/cph>
Fri, 3 Nov 1995 01:22:21 +0000 (01:22 +0000)
two threads read the same tqueue simultaneously, which violates the
assumption that each tqueue is read by only one thread.  This fix is a
kludge that will be replaced later by a redesigned communications
model.

v7/src/microcode/os2msg.c
v7/src/microcode/pros2io.c

index 95dcdfa12b9aa3d2eab33894fdfb0bcf3c62c161..71e3b50ca0a150e293d9dc7ae6fbf55d3820edce 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: os2msg.c,v 1.9 1995/04/28 07:04:59 cph Exp $
+$Id: os2msg.c,v 1.10 1995/11/03 01:22:09 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -481,20 +481,14 @@ subqueue_emptyp (qid_t qid)
 int
 OS2_tqueue_select (tqueue_t * tqueue, int blockp)
 {
-  while (1)
+  msg_t * message = (read_tqueue (tqueue, blockp));
+  if ((TQUEUE_TYPE (tqueue)) == tqt_scm)
     {
-      msg_t * message = (read_tqueue (tqueue, blockp));
-      if ((TQUEUE_TYPE (tqueue)) == tqt_scm)
-       {
-         process_interrupt_messages ();
-         if (pending_interrupts_p ())
-           return (-2);
-       }
-      if (message != 0)
-       return (MSG_SENDER (message));
-      if (!blockp)
-       return (-1);
+      process_interrupt_messages ();
+      if (pending_interrupts_p ())
+       return (-2);
     }
+  return ((message != 0) ? (MSG_SENDER (message)) : (-1));
 }
 
 static msg_t *
@@ -598,6 +592,16 @@ read_std_tqueue (tqueue_t * tqueue, int blockp)
       (void) OS2_reset_event_semaphore (STD_TQUEUE_EVENT (tqueue));
       OS2_release_mutex_semaphore (STD_TQUEUE_MUTEX (tqueue));
       (void) OS2_wait_event_semaphore ((STD_TQUEUE_EVENT (tqueue)), 1);
+      /* Don't wait more than once; the caller must be prepared to
+        call again if a message is required.  The reason this is
+        necessary is that two threads may be waiting on the same
+        tqueue at the same time, and when a message shows up, the
+        wrong thread might read it.  If we allowed the loop to
+        continue, the thread that was waiting for the message would
+        wake up, see no message, and go to sleep; meanwhile, the
+        other thread has already stored the message in the correct
+        subqueue.  */
+      blockp = 0;
     }
 }
 
index a43e84d6620e107feabc9708c1d2cde0f4bbb7d5..86cc37c96251f40a92d58bd407cde24952fdc1bb 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: pros2io.c,v 1.4 1995/04/28 06:59:29 cph Exp $
+$Id: pros2io.c,v 1.5 1995/11/03 01:22:21 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -106,6 +106,7 @@ DEFINE_PRIMITIVE ("OS2-SELECT-REGISTRY-TEST", Prim_OS2_select_registry_test, 3,
 
     /* This first phase checks the qid subqueues and OS2_scheme_tqueue
        for any previously-queued input.  */
+  check_for_input:
     for (qid = 0; (qid <= QID_MAX); qid += 1)
       {
        (results [qid]) = 0;
@@ -132,8 +133,10 @@ DEFINE_PRIMITIVE ("OS2-SELECT-REGISTRY-TEST", Prim_OS2_select_registry_test, 3,
            (OS2_scheme_tqueue_avail_map [qid]) = 0;
          n = (OS2_tqueue_select (OS2_scheme_tqueue, blockp));
          if (n == (-1))
-           break;
-         else if (n < 0)
+           /* If we're unblocked and there's no message in the
+              tqueue, go back and check for input again.  */
+           goto check_for_input;
+         if (n < 0)
            interruptp = 1;
          else
            for (qid = 0; (qid <= QID_MAX); qid += 1)