From 8ff4d3a26c4d5c8c63033749fabf9f0a7d39b76e Mon Sep 17 00:00:00 2001
From: Matt Birkholz <puck@birchwood-abbey.net>
Date: Sun, 19 Jul 2015 09:03:07 -0700
Subject: [PATCH] Add SIGALRM distributor.

---
 src/microcode/ossmp.h |  1 +
 src/microcode/uxsig.c | 60 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/src/microcode/ossmp.h b/src/microcode/ossmp.h
index c141102dd..da4b85a02 100644
--- a/src/microcode/ossmp.h
+++ b/src/microcode/ossmp.h
@@ -72,6 +72,7 @@ extern void smp_gc_finish (void);
 
 extern void smp_kill_gc (processor_t *);
 extern void smp_kill_timer (processor_t *);
+extern void smp_timer_interrupt (void);
 
 #ifdef ENABLE_DEBUGGING_TOOLS
 
diff --git a/src/microcode/uxsig.c b/src/microcode/uxsig.c
index e00712e9b..1dc7fd303 100644
--- a/src/microcode/uxsig.c
+++ b/src/microcode/uxsig.c
@@ -519,10 +519,62 @@ smp_kill_gc (processor_t *p)
   pthread_kill (p->pthread, SIGUSR2);
 }
 
+static volatile processor_t *next_timer = NULL;
+static pthread_mutex_t nt_mutex = MUTEX_INITIALIZER;
+#ifdef ENABLE_DEBUGGING_TOOLS
+#  define LOCK_NT() do							\
+{									\
+  int err = pthread_mutex_lock (&nt_mutex);				\
+  assert (err == 0);							\
+} while (false)
+#  define UNLOCK_NT() do						\
+{									\
+  int err = pthread_mutex_unlock (&nt_mutex);				\
+  assert (err == 0);							\
+} while (false)
+#else
+#  define LOCK_NT() do							\
+{									\
+  int err = pthread_mutex_lock (&nt_mutex);				\
+  if (err)								\
+    error_with_argument (err);						\
+} while (false)
+#  define UNLOCK_NT() do						\
+{									\
+  int err = pthread_mutex_unlock (&nt_mutex);				\
+  if (err)								\
+    error_with_argument (err);						\
+} while (false)
+#endif
+
 void
 smp_kill_timer (processor_t *p)
 {
+  block_signals ();
+  LOCK_NT();
+  next_timer = p;
   pthread_kill (p->pthread, SIGALRM);
+  UNLOCK_NT();
+  unblock_signals ();
+}
+
+void
+smp_timer_interrupt (void)
+{
+  volatile processor_t *p;
+
+  LOCK_NT();
+  p = next_timer;
+  if (p == NULL)
+    p = processors;
+  if (p == self)
+    {
+      request_timer_interrupt ();
+      next_timer = p->next;
+    }
+  else
+    pthread_kill (p->pthread, SIGALRM);
+  UNLOCK_NT();
 }
 
 #endif /* ENABLE_SMP */
@@ -536,7 +588,11 @@ smp_kill_timer (processor_t *p)
 static
 DEFUN_STD_HANDLER (sighnd_timer,
 {
+#ifndef ENABLE_SMP
   request_timer_interrupt ();
+#else
+  smp_timer_interrupt ();
+#endif
 })
 
 #else /* not HAVE_SETITIMER */
@@ -547,7 +603,11 @@ static
 DEFUN_STD_HANDLER (sighnd_timer,
 {
   reschedule_alarm ();
+#ifndef ENABLE_SMP
   request_timer_interrupt ();
+#else
+  smp_timer_interrupt ();
+#endif
 })
 
 #endif /* not HAVE_SETITIMER */
-- 
2.25.1