X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fposix%2FItimer.c;h=e46bb12546fb54fa31a8f61d2c23b942eb3cf4e6;hb=cf5905ea24904cf73a041fd7535e8723a668cb9a;hp=51e08f82803a2f84e9b0a610174571557bd9f8b3;hpb=8d71be7cbd079f5eab23484a53a43b59dd0399e5;p=ghc-hetmet.git diff --git a/rts/posix/Itimer.c b/rts/posix/Itimer.c index 51e08f8..e46bb12 100644 --- a/rts/posix/Itimer.c +++ b/rts/posix/Itimer.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------------- * - * (c) The GHC Team, 1995-1999 + * (c) The GHC Team, 1995-2007 * * Interval timer for profiling and pre-emptive scheduling. * @@ -16,15 +16,15 @@ * Hence, we use the old-fashioned @setitimer@ that just about everyone seems * to support. So much for standards. */ + +#include "PosixSource.h" #include "Rts.h" -#include "RtsFlags.h" -#include "Timer.h" + #include "Ticker.h" -#include "posix/Itimer.h" +#include "Itimer.h" #include "Proftimer.h" -#include "Storage.h" #include "Schedule.h" -#include "posix/Select.h" +#include "Select.h" /* As recommended in the autoconf manual */ # ifdef TIME_WITH_SYS_TIME @@ -42,6 +42,8 @@ # include #endif +#include + /* Major bogosity: * * In the threaded RTS, we can't set the virtual timer because the @@ -78,9 +80,10 @@ #elif defined(HAVE_SETITIMER) -# ifdef THREADED_RTS +# if defined(THREADED_RTS) || !defined(HAVE_SETITIMER_VIRTUAL) // 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. +// We also use it if we don't have a virtual timer (trac #2883). # define ITIMER_SIGNAL SIGALRM # define ITIMER_FLAVOUR ITIMER_REAL # else @@ -95,9 +98,11 @@ #endif #if defined(USE_TIMER_CREATE) -timer_t timer; +static timer_t timer; #endif +static nat itimer_interval = 50; + static void install_vtalrm_handler(TickProc handle_tick) @@ -127,7 +132,7 @@ install_vtalrm_handler(TickProc handle_tick) } void -initTicker (TickProc handle_tick) +initTicker (nat ms, TickProc handle_tick) { install_vtalrm_handler(handle_tick); @@ -135,10 +140,15 @@ initTicker (TickProc handle_tick) timestamp = getourtimeofday(); #endif + itimer_interval = ms; + #if defined(USE_TIMER_CREATE) { struct sigevent ev; + // Keep programs like valgrind happy + memset(&ev, 0, sizeof(ev)); + ev.sigev_notify = SIGEV_SIGNAL; ev.sigev_signo = ITIMER_SIGNAL; @@ -151,14 +161,14 @@ initTicker (TickProc handle_tick) } void -startTicker(nat ms) +startTicker(void) { #if defined(USE_TIMER_CREATE) { struct itimerspec it; - it.it_value.tv_sec = ms / 1000; - it.it_value.tv_nsec = (ms % 1000) * 1000000; + it.it_value.tv_sec = itimer_interval / 1000; + it.it_value.tv_nsec = (itimer_interval % 1000) * 1000000; it.it_interval = it.it_value; if (timer_settime(timer, 0, &it, NULL) != 0) { @@ -170,8 +180,8 @@ startTicker(nat ms) { struct itimerval it; - it.it_value.tv_sec = ms / 1000; - it.it_value.tv_usec = (ms % 1000) * 1000; + it.it_value.tv_sec = itimer_interval / 1000; + it.it_value.tv_usec = (itimer_interval % 1000) * 1000; it.it_interval = it.it_value; if (setitimer(ITIMER_FLAVOUR, &it, NULL) != 0) { @@ -211,36 +221,13 @@ stopTicker(void) } void -exitTicker(void) +exitTicker (rtsBool wait STG_UNUSED) { +#if defined(USE_TIMER_CREATE) timer_delete(timer); // ignore errors - we don't really care if it fails. -} - -#if 0 -/* Currently unused */ -void -block_vtalrm_signal(void) -{ - sigset_t signals; - - sigemptyset(&signals); - sigaddset(&signals, ITIMER_SIGNAL); - - (void) sigprocmask(SIG_BLOCK, &signals, NULL); -} - -void -unblock_vtalrm_signal(void) -{ - sigset_t signals; - - sigemptyset(&signals); - sigaddset(&signals, ITIMER_SIGNAL); - - (void) sigprocmask(SIG_UNBLOCK, &signals, NULL); -} #endif +} /* gettimeofday() takes around 1us on our 500MHz PIII. Since we're * only calling it 50 times/s, it shouldn't have any great impact. @@ -253,7 +240,14 @@ getourtimeofday(void) interval = RtsFlags.MiscFlags.tickInterval; if (interval == 0) { interval = 50; } gettimeofday(&tv, (struct timezone *) NULL); - // cast to lnat because nat may be 64 bit when int is only 32 bit - return ((lnat)tv.tv_sec * 1000 / interval + - (lnat)tv.tv_usec / (interval * 1000)); + + // Avoid overflow when we multiply seconds by 1000. See #2848 + return (lnat)((StgWord64)tv.tv_sec * 1000 / interval + + (StgWord64)tv.tv_usec / (interval * 1000)); +} + +int +rtsTimerSignal(void) +{ + return ITIMER_SIGNAL; }