X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FItimer.c;h=bbc87384e0bd648448d35685ecba57c062412f70;hb=73641e01ee9dfbe83f8c6225c1f6ae2e7d621b63;hp=1d63adf47f62b3f302d704ce99f7552a15392c80;hpb=bc5c802181b513216bc88f0d1ec9574157ee05fe;p=ghc-hetmet.git diff --git a/ghc/rts/Itimer.c b/ghc/rts/Itimer.c index 1d63adf..bbc8738 100644 --- a/ghc/rts/Itimer.c +++ b/ghc/rts/Itimer.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Itimer.c,v 1.23 2001/08/14 13:40:09 sewardj Exp $ + * $Id: Itimer.c,v 1.31 2002/08/16 13:29:06 simonmar Exp $ * * (c) The GHC Team, 1995-1999 * @@ -43,10 +43,14 @@ # include #endif -lnat total_ticks = 0; +#ifdef HAVE_SIGNAL_H +# include +#endif + +static lnat total_ticks = 0; /* ticks left before next pre-emptive context switch */ -int ticks_to_ctxt_switch = 0; +static int ticks_to_ctxt_switch = 0; /* ----------------------------------------------------------------------------- Tick handler @@ -61,6 +65,7 @@ int ticks_to_ctxt_switch = 0; static void #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) + CALLBACK handle_tick(UINT uID STG_UNUSED, UINT uMsg STG_UNUSED, DWORD dwUser STG_UNUSED, DWORD dw1 STG_UNUSED, DWORD d STG_UNUSED) @@ -74,11 +79,6 @@ handle_tick(int unused STG_UNUSED) handleProfTick(); #endif - /* so we can get a rough indication of the current time at any point - * without having to call gettimeofday() (see Select.c): - */ - ticks_since_timestamp++; - if (RtsFlags.ConcFlags.ctxtSwitchTicks > 0) { ticks_to_ctxt_switch--; if (ticks_to_ctxt_switch <= 0) { @@ -102,10 +102,12 @@ handle_tick(int unused STG_UNUSED) #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) -LPTIMECALLBACK vtalrm_cback; +static LPTIMECALLBACK vtalrm_cback; +static unsigned int vtalrm_id = 0; +static unsigned int period = -1; -nat -initialize_virtual_timer(nat ms) +int +startVirtTimer(nat ms) { /* On Win32 setups that don't have support for setitimer(), we use the MultiMedia API's timer @@ -114,31 +116,65 @@ initialize_virtual_timer(nat ms) The delivery of ticks isn't free; the performance hit should be checked. */ unsigned int delay; - static unsigned int vtalrm_id; - - if (ms) { - delay = timeBeginPeriod(1); + TIMECAPS tc; + + vtalrm_cback = handle_tick; + + if ( timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR) { + period = tc.wPeriodMin; + delay = timeBeginPeriod(period); if (delay == TIMERR_NOCANDO) { /* error of some sort. */ - return delay; + return -1; } - vtalrm_id = - timeSetEvent(ms, /* event every `delay' milliseconds. */ - 1, /* precision is within 1 ms */ - vtalrm_cback, - TIME_CALLBACK_FUNCTION, /* ordinary callback */ - TIME_PERIODIC); } else { - timeKillEvent(vtalrm_id); - timeEndPeriod(1); + return -1; } + +#ifdef PROFILING + initProfTimer(); +#endif + + vtalrm_id = + timeSetEvent(ms, /* event every `delay' milliseconds. */ + 1, /* precision is within 1 ms */ + vtalrm_cback, + TIME_CALLBACK_FUNCTION, /* ordinary callback */ + TIME_PERIODIC); return 0; } + +int +stopVirtTimer() +{ + /* Shutdown the MM timer */ + if ( vtalrm_id != 0 ) { + timeKillEvent(vtalrm_id); + } + if (period > 0) { + timeEndPeriod(period); + } + + return 0; +} #else +static +int +install_vtalrm_handler(void) +{ + struct sigaction action; + + action.sa_handler = handle_tick; + + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + return sigaction(SIGVTALRM, &action, NULL); +} -nat -initialize_virtual_timer(nat ms) +int +startVirtTimer(nat ms) { # ifndef HAVE_SETITIMER /* fprintf(stderr, "No virtual timer on this system\n"); */ @@ -146,8 +182,13 @@ initialize_virtual_timer(nat ms) # else struct itimerval it; + install_vtalrm_handler(); + timestamp = getourtimeofday(); - ticks_since_timestamp = 0; + +#ifdef PROFILING + initProfTimer(); +#endif it.it_value.tv_sec = ms / 1000; it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec)); @@ -156,19 +197,38 @@ initialize_virtual_timer(nat ms) # endif } -#endif /* !cygwin32_TARGET_OS */ +int +stopVirtTimer() +{ +# ifndef HAVE_SETITIMER + /* fprintf(stderr, "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_VIRTUAL, &it, NULL)); +# endif +} + +#endif /* !{mingw,cygwin32}_TARGET_OS */ # if 0 /* This is a potential POSIX version */ -nat -initialize_virtual_timer(nat ms) +int +startVirtTimer(nat ms) { struct sigevent se; struct itimerspec it; timer_t tid; timestamp = getourtimeofday(); - ticks_since_timestamp = 0; + +#ifdef PROFILING + initProfTimer(); +#endif se.sigev_notify = SIGEV_SIGNAL; se.sigev_signo = SIGVTALRM; @@ -179,32 +239,34 @@ 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); + return 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; -} - -#else -int -install_vtalrm_handler(void) +stopVirtTimer() { - 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 defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) +#else void block_vtalrm_signal(void) {