diff options
author | Simon Marlow <simonmar@microsoft.com> | 2007-03-02 11:31:04 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2007-03-02 11:31:04 +0000 |
commit | e30aca19def5c629a8429bd57e56535b7f8f85c8 (patch) | |
tree | 64513fe1bd809cb0e8442df826a03fb73c324103 | |
parent | 090bff7e86dbad7c429532994f3f2fe9d4d8b8ea (diff) | |
download | haskell-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.ac | 2 | ||||
-rw-r--r-- | rts/Ticker.h | 4 | ||||
-rw-r--r-- | rts/Timer.c | 8 | ||||
-rw-r--r-- | rts/Timer.h | 4 | ||||
-rw-r--r-- | rts/posix/Itimer.c | 169 | ||||
-rw-r--r-- | rts/win32/Ticker.c | 11 |
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; } |