summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2007-03-02 11:31:04 +0000
committerSimon Marlow <simonmar@microsoft.com>2007-03-02 11:31:04 +0000
commite30aca19def5c629a8429bd57e56535b7f8f85c8 (patch)
tree64513fe1bd809cb0e8442df826a03fb73c324103
parent090bff7e86dbad7c429532994f3f2fe9d4d8b8ea (diff)
downloadhaskell-e30aca19def5c629a8429bd57e56535b7f8f85c8.tar.gz
Use timer_create() for the interval timer, if available
This lets the threaded RTS use SIGVTALRM rather than SIGALRM for its interval timer signal, so the threaded and non-threaded RTS are compatible. It unfortunately doesn't completely fix #850/#1156, for that we really have to use a restartable sleep instead of usleep(). Also I cleaned up the timer API a little: instead of returning an error value that ultimately gets ignored, we now report errors from system calls and exit.
-rw-r--r--configure.ac2
-rw-r--r--rts/Ticker.h4
-rw-r--r--rts/Timer.c8
-rw-r--r--rts/Timer.h4
-rw-r--r--rts/posix/Itimer.c169
-rw-r--r--rts/win32/Ticker.c11
6 files changed, 108 insertions, 90 deletions
diff --git a/configure.ac b/configure.ac
index 8cf4d61819..fbb9d293a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1196,7 +1196,7 @@ AC_COMPILE_IFELSE(
dnl ** check for librt
AC_CHECK_LIB(rt, clock_gettime)
-AC_CHECK_FUNCS(clock_gettime)
+AC_CHECK_FUNCS(clock_gettime timer_create timer_settime)
dnl ** check for Apple's "interesting" long double compatibility scheme
AC_MSG_CHECKING(for printf\$LDBLStub)
diff --git a/rts/Ticker.h b/rts/Ticker.h
index f9555768b5..b06890a049 100644
--- a/rts/Ticker.h
+++ b/rts/Ticker.h
@@ -9,7 +9,7 @@
#ifndef TICKER_H
#define TICKER_H
-extern int startTicker( nat ms, TickProc handle_tick );
-extern int stopTicker ( void );
+extern void startTicker( nat ms, TickProc handle_tick );
+extern void stopTicker ( void );
#endif /* TICKER_H */
diff --git a/rts/Timer.c b/rts/Timer.c
index 8088600246..493fe3d35f 100644
--- a/rts/Timer.c
+++ b/rts/Timer.c
@@ -83,18 +83,18 @@ handle_tick(int unused STG_UNUSED)
#endif
}
-int
+void
startTimer(void)
{
#ifdef PROFILING
initProfTimer();
#endif
- return startTicker(RtsFlags.MiscFlags.tickInterval, handle_tick);
+ startTicker(RtsFlags.MiscFlags.tickInterval, handle_tick);
}
-int
+void
stopTimer(void)
{
- return stopTicker();
+ stopTicker();
}
diff --git a/rts/Timer.h b/rts/Timer.h
index 1fe857d969..6d3c4150b0 100644
--- a/rts/Timer.h
+++ b/rts/Timer.h
@@ -11,7 +11,7 @@
typedef void (*TickProc)(int);
-extern int startTimer(void);
-extern int stopTimer(void);
+extern void startTimer(void);
+extern void stopTimer(void);
#endif /* TIMER_H */
diff --git a/rts/posix/Itimer.c b/rts/posix/Itimer.c
index 715cf5af3c..8600c0a99c 100644
--- a/rts/posix/Itimer.c
+++ b/rts/posix/Itimer.c
@@ -52,9 +52,7 @@
*
* (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.
+ * results.
*
* (2) save/restore the virtual timer around excursions into STG land.
* Sounds great, but I tried it and the resolution of the virtual timer
@@ -68,16 +66,42 @@
*
* For now, we're using (1), but this needs a better solution. --SDM
*/
-#ifdef THREADED_RTS
-#define ITIMER_FLAVOUR ITIMER_REAL
-#define ITIMER_SIGNAL SIGALRM
+
+#if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
+
+# define USE_TIMER_CREATE
+# define ITIMER_SIGNAL SIGVTALRM
+# ifdef THREADED_RTS
+# define TIMER_FLAVOUR CLOCK_REALTIME
+# else
+# define TIMER_FLAVOUR CLOCK_PROCESS_CPUTIME_ID
+# endif
+
+#elif defined(HAVE_SETITIMER)
+
+# define USE_ITIMER
+# ifdef THREADED_RTS
+// Oh dear, we have to use SIGALRM if there's no timer_create and
+// we're using the THREADED_RTS. This leads to problems, see bug #850.
+# define ITIMER_SIGNAL SIGALRM
+# define ITIMER_FLAVOUR ITIMER_REAL
+# else
+# define ITIMER_SIGNAL SIGVTALRM
+# define ITIMER_FLAVOUR ITIMER_VIRTUAL
+# endif
+
#else
-#define ITIMER_FLAVOUR ITIMER_VIRTUAL
-#define ITIMER_SIGNAL SIGVTALRM
+
+# error No way to set an interval timer.
+
+#endif
+
+#if defined(USE_TIMER_CREATE)
+timer_t timer;
#endif
static
-int
+void
install_vtalrm_handler(TickProc handle_tick)
{
struct sigaction action;
@@ -98,95 +122,86 @@ install_vtalrm_handler(TickProc handle_tick)
action.sa_flags = 0;
#endif
- return sigaction(ITIMER_SIGNAL, &action, NULL);
+ if (sigaction(ITIMER_SIGNAL, &action, NULL) == -1) {
+ sysErrorBelch("sigaction");
+ stg_exit(EXIT_FAILURE);
+ }
}
-int
+void
startTicker(nat ms, TickProc handle_tick)
{
-# ifndef HAVE_SETITIMER
- /* debugBelch("No virtual timer on this system\n"); */
- return -1;
-# else
- struct itimerval it;
-
install_vtalrm_handler(handle_tick);
#if !defined(THREADED_RTS)
timestamp = getourtimeofday();
#endif
- 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_FLAVOUR, &it, NULL));
-# endif
-}
-
-int
-stopTicker()
-{
-# ifndef HAVE_SETITIMER
- /* debugBelch("No virtual timer on this system\n"); */
- return -1;
-# else
- struct itimerval it;
-
- it.it_value.tv_sec = 0;
- it.it_value.tv_usec = 0;
- it.it_interval = it.it_value;
- return (setitimer(ITIMER_FLAVOUR, &it, NULL));
-# endif
-}
-
-# if 0
-/* This is a potential POSIX version */
-int
-startTicker(nat ms)
-{
- struct sigevent se;
- struct itimerspec it;
- timer_t tid;
-
-#if !defined(THREADED_RTS)
- timestamp = getourtimeofday();
-#endif
-
- se.sigev_notify = SIGEV_SIGNAL;
- 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");
+#if defined(USE_TIMER_CREATE)
+ {
+ struct itimerspec it;
+ struct sigevent ev;
+
+ ev.sigev_notify = SIGEV_SIGNAL;
+ ev.sigev_signo = ITIMER_SIGNAL;
+
+ it.it_value.tv_sec = ms / 1000;
+ it.it_value.tv_nsec = (ms % 1000) * 1000000;
+ it.it_interval = it.it_value;
+
+ if (timer_create(TIMER_FLAVOUR, &ev, &timer) != 0) {
+ sysErrorBelch("timer_create");
+ stg_exit(EXIT_FAILURE);
+ }
+
+ if (timer_settime(timer, 0, &it, NULL) != 0) {
+ sysErrorBelch("timer_settime");
+ stg_exit(EXIT_FAILURE);
+ }
}
- it.it_value.tv_sec = ms / 1000;
- it.it_value.tv_nsec = 1000000 * (ms - 1000 * it.it_value.tv_sec);
- it.it_interval = it.it_value;
- return timer_settime(tid, TIMER_RELTIME, &it, NULL);
+#else
+ {
+ struct itimerval it;
+
+ it.it_value.tv_sec = ms / 1000;
+ it.it_value.tv_usec = (ms % 1000) * 1000;
+ it.it_interval = it.it_value;
+
+ if (setitimer(ITIMER_FLAVOUR, &it, NULL) != 0) {
+ sysErrorBelch("setitimer");
+ stg_exit(EXIT_FAILURE);
+ }
+ }
+#endif
}
-int
-stopTicker()
+void
+stopTicker(void)
{
- struct sigevent se;
+#if defined(USE_TIMER_CREATE)
struct itimerspec it;
- timer_t tid;
-#if !defined(THREADED_RTS)
- timestamp = getourtimeofday();
-#endif
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_nsec = 0;
+ it.it_interval = it.it_value;
- se.sigev_notify = SIGEV_SIGNAL;
- 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");
+ if (timer_settime(timer, 0, &it, NULL) != 0) {
+ sysErrorBelch("timer_settime");
+ stg_exit(EXIT_FAILURE);
}
+#else
+ struct itimerval it;
+
it.it_value.tv_sec = 0;
- it.it_value.tv_nsec = 0;
+ it.it_value.tv_usec = 0;
it.it_interval = it.it_value;
- return timer_settime(tid, TIMER_RELTIME, &it, NULL);
+
+ if (setitimer(ITIMER_FLAVOUR, &it, NULL) != 0) {
+ sysErrorBelch("setitimer");
+ stg_exit(EXIT_FAILURE);
+ }
+#endif
}
-# endif
#if 0
/* Currently unused */
diff --git a/rts/win32/Ticker.c b/rts/win32/Ticker.c
index 7701a3b275..5b41494d47 100644
--- a/rts/win32/Ticker.c
+++ b/rts/win32/Ticker.c
@@ -74,7 +74,7 @@ TimerProc(PVOID param)
}
-int
+void
startTicker(nat ms, TickProc handle_tick)
{
unsigned threadId;
@@ -95,10 +95,14 @@ startTicker(nat ms, TickProc handle_tick)
(LPVOID)ms,
0,
&threadId);
- return (tickThread != 0);
+
+ if (tickThread == 0) {
+ sysErrorBelch("_beginthreadex");
+ stg_exit(EXIT_FAILURE);
+ }
}
-int
+void
stopTicker(void)
{
// We must wait for the ticker thread to terminate, since if we
@@ -125,5 +129,4 @@ stopTicker(void)
TerminateThread(tickThread, 0);
}
}
- return 0;
}