[project @ 2003-12-22 16:27:10 by simonmar]
authorsimonmar <unknown>
Mon, 22 Dec 2003 16:27:10 +0000 (16:27 +0000)
committersimonmar <unknown>
Mon, 22 Dec 2003 16:27:10 +0000 (16:27 +0000)
Fix threaded RTS problem that is currently causing the conc007 test to
loop indefinitely.  Comment from the source regarding this change:

/* Major bogosity:
 *
 * In the threaded RTS, we can't set the virtual timer because the
 * thread which has the virtual timer might be sitting waiting for a
 * capability, and the virtual timer only ticks in CPU time.
 *
 * So, possible solutions:
 *
 * (1) tick in realtime.  Not very good, because this ticker is used for
 *     profiling, and this will give us unreliable time profiling
 *     results.  Furthermore, this requires picking a single OS thread
 *     to be the timekeeper, which is a bad idea because the thread in
 *     question might just be making a temporary call into Haskell land.
 *
 * (2) save/restore the virtual timer around excursions into STG land.
 *     Sounds great, but I tried it and the resolution of the virtual timer
 *     isn't good enough (on Linux) - most of our excursions fall
 *     within the timer's resolution and we never make any progress.
 *
 * (3) have a virtual timer in every OS thread.  Might be reasonable,
 *     because most of the time there is only ever one of these
 *     threads running, so it approximates a single virtual timer.
 *     But still quite bogus (and I got crashes when I tried this).
 *
 * For now, we're using (1), but this needs a better solution. --SDM
 */

ghc/rts/Itimer.c

index 74801db..2f769d3 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Itimer.c,v 1.35 2003/03/29 00:27:11 sof Exp $
+ * $Id: Itimer.c,v 1.36 2003/12/22 16:27:10 simonmar Exp $
  *
  * (c) The GHC Team, 1995-1999
  *
 # include <signal.h>
 #endif
 
+/* Major bogosity:
+ * 
+ * In the threaded RTS, we can't set the virtual timer because the
+ * thread which has the virtual timer might be sitting waiting for a
+ * capability, and the virtual timer only ticks in CPU time.
+ *
+ * So, possible solutions:
+ *
+ * (1) tick in realtime.  Not very good, because this ticker is used for
+ *     profiling, and this will give us unreliable time profiling
+ *     results.  Furthermore, this requires picking a single OS thread
+ *     to be the timekeeper, which is a bad idea because the thread in
+ *     question might just be making a temporary call into Haskell land.
+ *
+ * (2) save/restore the virtual timer around excursions into STG land.
+ *     Sounds great, but I tried it and the resolution of the virtual timer
+ *     isn't good enough (on Linux) - most of our excursions fall
+ *     within the timer's resolution and we never make any progress.
+ *   
+ * (3) have a virtual timer in every OS thread.  Might be reasonable,
+ *     because most of the time there is only ever one of these
+ *     threads running, so it approximates a single virtual timer.
+ *     But still quite bogus (and I got crashes when I tried this).
+ *
+ * For now, we're using (1), but this needs a better solution. --SDM
+ */
+#ifdef RTS_SUPPORTS_THREADS
+#define ITIMER_FLAVOUR  ITIMER_REAL
+#define ITIMER_SIGNAL   SIGALRM
+#else
+#define ITIMER_FLAVOUR  ITIMER_VIRTUAL
+#define ITIMER_SIGNAL   SIGVTALRM
+#endif
+
 static
 int
 install_vtalrm_handler(TickProc handle_tick)
@@ -51,7 +85,7 @@ install_vtalrm_handler(TickProc handle_tick)
     sigemptyset(&action.sa_mask);
     action.sa_flags = 0;
 
-    return sigaction(SIGVTALRM, &action, NULL);
+    return sigaction(ITIMER_SIGNAL, &action, NULL);
 }
 
 int
@@ -70,7 +104,7 @@ startTicker(nat ms, TickProc handle_tick)
     it.it_value.tv_sec = ms / 1000;
     it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec));
     it.it_interval = it.it_value;
-    return (setitimer(ITIMER_VIRTUAL, &it, NULL));
+    return (setitimer(ITIMER_FLAVOUR, &it, NULL));
 # endif
 }
 
@@ -86,7 +120,7 @@ stopTicker()
     it.it_value.tv_sec = 0;
     it.it_value.tv_usec = 0;
     it.it_interval = it.it_value;
-    return (setitimer(ITIMER_VIRTUAL, &it, NULL));
+    return (setitimer(ITIMER_FLAVOUR, &it, NULL));
 # endif
 }
 
@@ -102,8 +136,8 @@ startTicker(nat ms)
     timestamp = getourtimeofday();
 
     se.sigev_notify = SIGEV_SIGNAL;
-    se.sigev_signo = SIGVTALRM;
-    se.sigev_value.sival_int = SIGVTALRM;
+    se.sigev_signo = ITIMER_SIGNAL;
+    se.sigev_value.sival_int = ITIMER_SIGNAL;
     if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
        barf("can't create virtual timer");
     }
@@ -123,8 +157,8 @@ stopTicker()
     timestamp = getourtimeofday();
 
     se.sigev_notify = SIGEV_SIGNAL;
-    se.sigev_signo = SIGVTALRM;
-    se.sigev_value.sival_int = SIGVTALRM;
+    se.sigev_signo = ITIMER_SIGNAL;
+    se.sigev_value.sival_int = ITIMER_SIGNAL;
     if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
        barf("can't create virtual timer");
     }
@@ -143,7 +177,7 @@ block_vtalrm_signal(void)
     sigset_t signals;
     
     sigemptyset(&signals);
-    sigaddset(&signals, SIGVTALRM);
+    sigaddset(&signals, ITIMER_SIGNAL);
 
     (void) sigprocmask(SIG_BLOCK, &signals, NULL);
 }
@@ -154,7 +188,7 @@ unblock_vtalrm_signal(void)
     sigset_t signals;
     
     sigemptyset(&signals);
-    sigaddset(&signals, SIGVTALRM);
+    sigaddset(&signals, ITIMER_SIGNAL);
 
     (void) sigprocmask(SIG_UNBLOCK, &signals, NULL);
 }