Forward SIGCHLD to the io-waiter.
authorMatt Birkholz <puck@birchwood-abbey.net>
Sun, 19 Jul 2015 17:31:14 +0000 (10:31 -0700)
committerMatt Birkholz <puck@birchwood-abbey.net>
Thu, 26 Nov 2015 08:09:46 +0000 (01:09 -0700)
Set/clear the new variable smp_io_blocked around calls to poll/select
so that subprocess_death (SIGCHLD) can wake a blocked processor
without having to ask Scheme which (if any) is running the io-waiter.
Wake the processor with a timer interrupt withOUT fiddling next_timer.

src/microcode/ossmp.h
src/microcode/prossmp.c
src/microcode/uxio.c
src/microcode/uxproc.c

index da4b85a02843cae1b9b5f85350fd5d70b2ce038d..4eafb509444912e67978f20feae545d72f66f865 100644 (file)
@@ -58,6 +58,7 @@ struct processor {
 };
 
 extern processor_t *processors;
+extern processor_t *smp_io_blocked;
 extern __thread processor_t *self;
 extern processor_t *gc_processor;
 
index eba3173eca05c275f7803353e25f6102c4c6856d..162fc8356f8a0132af697ad2912b2c21cac4024a 100644 (file)
@@ -60,6 +60,9 @@ static processor_t *threads_processor = NULL;
 /* The current pthread's processor. */
 __thread processor_t *self;
 
+/* The io-waiter's processor when it is blocked in test-select-registry. */
+processor_t *smp_io_blocked = NULL;
+
 extern int saved_processor_count;
 extern int saved_processor_heap_size;
 extern int saved_stack_size;
index 027f7c7e52171024ca621ae7a9d0a7793c100f04..5736e4eb160765f08767bb31947898e2ca6eabda 100644 (file)
@@ -33,6 +33,14 @@ USA.
 Tchannel OS_channel_table_size;
 struct channel * channel_table;
 
+#ifdef ENABLE_SMP
+#  define SMP_IO_BLOCKED smp_io_blocked = self
+#  define SMP_IO_UNBLOCKED smp_io_blocked = NULL
+#else
+#  define SMP_IO_BLOCKED do {} while (false)
+#  define SMP_IO_UNBLOCKED do {} while (false)
+#endif
+
 #ifndef HAVE_POLL
 #ifdef HAVE_SELECT
 static struct timeval zero_timeout;
@@ -600,17 +608,21 @@ safe_poll (struct pollfd *fds, nfds_t nfds, int blockp)
        }
       else
        {
+         SMP_IO_BLOCKED;
          n = (UX_ppoll (fds, nfds, NULL, &old));
+         SMP_IO_UNBLOCKED;
        }
       UX_sigprocmask (SIG_SETMASK, &old, NULL);
     }
 #else /* not HAVE_PPOLL */
     {
+      SMP_IO_BLOCKED;
       INTERRUPTABLE_EXTENT
        (n, (((OS_process_any_status_change ())
              || ((GET_INT_CODE) != 0))
             ? ((errno = EINTR), (-1))
             : (UX_poll (fds, nfds, (blockp ? INFTIM : 0)))));
+      SMP_IO_UNBLOCKED;
     }
 #endif
 
@@ -814,18 +826,22 @@ safe_select (int nfds, SELECT_TYPE *readfds, SELECT_TYPE *writefds, int blockp)
        }
       else
        {
+         SMP_IO_BLOCKED;
          n = (UX_pselect (nfds, readfds, writefds, NULL, NULL, &old));
+         SMP_IO_UNBLOCKED;
        }
       UX_sigprocmask (SIG_SETMASK, &old, NULL);
     }
 #else /* not HAVE_PSELECT */
     {
+      SMP_IO_BLOCKED;
       INTERRUPTABLE_EXTENT
        (n, (((OS_process_any_status_change ())
              || ((GET_INT_CODE) != 0))
             ? ((errno = EINTR), (-1))
             : (UX_select (nfds, readfds, writefds, NULL,
                           (blockp ? NULL : &zero_timeout)))));
+      SMP_IO_UNBLOCKED;
     }
 #endif
 
index 9ae28802944ef3dabed4199b12053b9e5d18cb68..9dc32b367e14a8a6a34bcb2a24d97c48279cf6da 100644 (file)
@@ -58,6 +58,12 @@ static Tprocess foreground_child_process;
 static long process_tick;
 static long sync_tick;
 
+#ifdef ENABLE_SMP
+#  ifdef ENABLE_DEBUGGING_TOOLS
+#    define ENABLE_SMP_DEBUGGING 1
+#  endif
+#endif
+
 #define NEW_RAW_STATUS(process, status, reason) do                     \
 {                                                                      \
   (PROCESS_RAW_STATUS (process)) = (status);                           \
@@ -719,7 +725,14 @@ find_process (pid_t pid)
 static void
 subprocess_death (pid_t pid, int * status)
 {
-  Tprocess process = (find_process (pid));
+  Tprocess process;
+
+#ifdef ENABLE_SMP_DEBUGGING
+  if (smp_trace_p)
+    outf_error_line (";%d subprocess_death: %d blocked", self->id,
+                    (smp_io_blocked != NULL ? smp_io_blocked->id : -1));
+#endif
+  process = (find_process (pid));
   if (process != NO_PROCESS)
     {
       if (WIFEXITED (*status))
@@ -732,6 +745,22 @@ subprocess_death (pid_t pid, int * status)
        NEW_RAW_STATUS
          (process, process_status_signalled, (WTERMSIG (*status)));
     }
+#ifdef ENABLE_SMP
+  if (smp_io_blocked != NULL && smp_io_blocked != self)
+    {
+# ifdef ENABLE_SMP_DEBUGGING
+      if (smp_trace_p)
+       outf_error_line (";%d subprocess_death: interrupting %d",
+                        self->id, smp_io_blocked->id);
+# endif
+      pthread_kill (smp_io_blocked->pthread, SIGALRM);
+# ifdef ENABLE_SMP_DEBUGGING
+      if (smp_trace_p)
+       outf_error_line (";%d subprocess_death: interrupted %d",
+                        self->id, smp_io_blocked->id);
+# endif
+    }
+#endif
 }
 
 static void