X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FItimer.c;h=74801dba542ca6a45b0cf2cc7dc97c20ff2c4cf9;hb=4cdc197978cf22419b2f4344a19c87c474c8fc1c;hp=1bdd2bb4a4294634cc8a9d7b7570206e5d1005f2;hpb=bbe3617e46aa95ecb2519285d824a64bca17d228;p=ghc-hetmet.git diff --git a/ghc/rts/Itimer.c b/ghc/rts/Itimer.c index 1bdd2bb..74801db 100644 --- a/ghc/rts/Itimer.c +++ b/ghc/rts/Itimer.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Itimer.c,v 1.9 2000/02/28 10:57:44 simonmar Exp $ + * $Id: Itimer.c,v 1.35 2003/03/29 00:27:11 sof Exp $ * * (c) The GHC Team, 1995-1999 * @@ -17,13 +17,11 @@ * Hence, we use the old-fashioned @setitimer@ that just about everyone seems * to support. So much for standards. */ - -#if !defined(_AIX) -# define NON_POSIX_SOURCE -#endif - #include "Rts.h" +#include "RtsFlags.h" +#include "Timer.h" #include "Itimer.h" +#include "Proftimer.h" #include "Schedule.h" /* As recommended in the autoconf manual */ @@ -38,124 +36,71 @@ # endif # endif -#if HAVE_WINDOWS_H -# include +#ifdef HAVE_SIGNAL_H +# include #endif - -lnat total_ticks = 0; -rtsBool do_prof_ticks = rtsFalse; -static void handle_tick(int unused STG_UNUSED); - -/* ----------------------------------------------------------------------------- - Tick handler - - We use the ticker for two things: supporting threadDelay, and time - profiling. - - SMP note: this signal could be delivered to *any* thread. We have - to ensure that it doesn't matter which thread actually runs the - signal handler. - -------------------------------------------------------------------------- */ - -static void -handle_tick(int unused STG_UNUSED) +static +int +install_vtalrm_handler(TickProc handle_tick) { - total_ticks++; + struct sigaction action; -#ifdef PROFILING - if (do_prof_ticks == rtsTrue) { - CCS_TICK(CCCS); - } -#endif + action.sa_handler = handle_tick; + + sigemptyset(&action.sa_mask); + action.sa_flags = 0; - /* For threadDelay etc., see Select.c */ - ticks_since_select++; + return sigaction(SIGVTALRM, &action, NULL); } +int +startTicker(nat ms, TickProc handle_tick) +{ +# ifndef HAVE_SETITIMER + /* fprintf(stderr, "No virtual timer on this system\n"); */ + return -1; +# else + struct itimerval it; -/* - * Handling timer events under cygwin32 is not done with signal/setitimer. - * Instead of the two steps of first registering a signal handler to handle - * \tr{SIGVTALRM} and then start generating them via @setitimer()@, we use - * the Multimedia API (MM) and its @timeSetEvent@. (Internally, the MM API - * creates a separate thread that will notify the main thread of timer - * expiry). -- SOF 7/96 - * - * 11/98: if the cygwin DLL supports setitimer(), then use it instead. - */ + install_vtalrm_handler(handle_tick); -#if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) + timestamp = getourtimeofday(); -/* - vtalrm_handler is assigned and set up in Signals.c - - vtalrm_id (defined in Signals.c) holds - the system id for the current timer (used to - later block/kill it.) -*/ -extern nat vtalrm_id; -TIMECALLBACK *vtalrm_cback; - -nat -initialize_virtual_timer(nat ms) -{ -# ifdef PROFILING - /* On Win32 setups that don't have support for - setitimer(), we use the MultiMedia API's timer - support. - - As the delivery of ticks isn't free, we only - enable it if we really needed, i.e., when profiling. - (the RTS now also needs timer ticks to implement - threadDelay in non-profiling mode, but the pure - Win32 port doesn't support that.....yet.) - */ - unsigned int delay,vtalrm_id; - - delay = timeBeginPeriod(1); - if (delay == TIMERR_NOCANDO) { /* error of some sort. */ - return delay; - } - vtalrm_id = - timeSetEvent(ms, /* event every `delay' milliseconds. */ - 1, /* precision is within 5 millisecs. */ - (LPTIMECALLBACK)vtalrm_cback, - 0, - TIME_PERIODIC); + 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)); # endif - return 0; } - -#else -nat -initialize_virtual_timer(nat ms) +int +stopTicker() { # ifndef HAVE_SETITIMER - fprintf(stderr, "No virtual timer on this system\n"); + /* fprintf(stderr, "No virtual timer on this system\n"); */ return -1; # else struct itimerval it; - - it.it_value.tv_sec = ms / 1000; - it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec)); + + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 0; it.it_interval = it.it_value; return (setitimer(ITIMER_VIRTUAL, &it, NULL)); # endif } -#endif /* !cygwin32_TARGET_OS */ - # if 0 /* This is a potential POSIX version */ -nat -initialize_virtual_timer(nat ms) +int +startTicker(nat ms) { struct sigevent se; struct itimerspec it; timer_t tid; + timestamp = getourtimeofday(); + se.sigev_notify = SIGEV_SIGNAL; se.sigev_signo = SIGVTALRM; se.sigev_value.sival_int = SIGVTALRM; @@ -165,32 +110,33 @@ initialize_virtual_timer(nat ms) 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; - timer_settime(tid, TIMER_RELTIME, &it, NULL); -} -# endif - -#if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) -int -install_vtalrm_handler(void) -{ - vtalrm_cback = handle_tick; - return 0; + return timer_settime(tid, TIMER_RELTIME, &it, NULL); } -#else int -install_vtalrm_handler(void) +stopTicker() { - struct sigaction action; - - action.sa_handler = handle_tick; + struct sigevent se; + struct itimerspec it; + timer_t tid; - sigemptyset(&action.sa_mask); - action.sa_flags = 0; + timestamp = getourtimeofday(); - return sigaction(SIGVTALRM, &action, NULL); + se.sigev_notify = SIGEV_SIGNAL; + se.sigev_signo = SIGVTALRM; + se.sigev_value.sival_int = SIGVTALRM; + if (timer_create(CLOCK_VIRTUAL, &se, &tid)) { + barf("can't create virtual timer"); + } + it.it_value.tv_sec = 0; + it.it_value.tv_nsec = 0; + it.it_interval = it.it_value; + return timer_settime(tid, TIMER_RELTIME, &it, NULL); } +# endif +#if 0 +/* Currently unused */ void block_vtalrm_signal(void) { @@ -213,3 +159,16 @@ unblock_vtalrm_signal(void) (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. + */ +unsigned int +getourtimeofday(void) +{ + struct timeval tv; + gettimeofday(&tv, (struct timezone *) NULL); + return (tv.tv_sec * TICK_FREQUENCY + + tv.tv_usec * TICK_FREQUENCY / 1000000); +} +