X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=ghc%2Frts%2FItimer.c;h=623839189fb4b3fcd6cf9711a1b6d4433785cb9c;hb=5acd2909936a1e56db8386ebccf66e0347012ad6;hp=60e30e786d649780815d0e8d0d21faabc00118ce;hpb=b9d8ddb91c9360e3165244520f31dcd28c396825;p=ghc-hetmet.git diff --git a/ghc/rts/Itimer.c b/ghc/rts/Itimer.c index 60e30e7..6238391 100644 --- a/ghc/rts/Itimer.c +++ b/ghc/rts/Itimer.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Itimer.c,v 1.13 2000/04/03 15:54:49 simonmar Exp $ + * $Id: Itimer.c,v 1.19 2000/10/06 11:05:57 rrt Exp $ * * (c) The GHC Team, 1995-1999 * @@ -23,6 +23,7 @@ #endif #include "Rts.h" +#include "RtsFlags.h" #include "Itimer.h" #include "Proftimer.h" #include "Schedule.h" @@ -45,18 +46,23 @@ lnat total_ticks = 0; +/* ticks left before next pre-emptive context switch */ +int ticks_to_ctxt_switch = 0; + static void #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) CALLBACK -#endif +handle_tick(UINT uID STG_UNUSED, UINT uMsg STG_UNUSED, DWORD dwUser STG_UNUSED, + DWORD dw1 STG_UNUSED, DWORD d STG_UNUSED); +#else handle_tick(int unused STG_UNUSED); +#endif /* ----------------------------------------------------------------------------- Tick handler - We use the ticker for two things: supporting threadDelay, and time - profiling. + We use the ticker for 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 @@ -67,8 +73,11 @@ static void #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) CALLBACK -#endif +handle_tick(UINT uID STG_UNUSED, UINT uMsg STG_UNUSED, DWORD dwUser STG_UNUSED, + DWORD dw1 STG_UNUSED, DWORD d STG_UNUSED) +#else handle_tick(int unused STG_UNUSED) +#endif { total_ticks++; @@ -76,8 +85,16 @@ handle_tick(int unused STG_UNUSED) handleProfTick(); #endif - /* For threadDelay etc., see Select.c */ - ticks_since_select++; + /* 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++; + + ticks_to_ctxt_switch--; + if (ticks_to_ctxt_switch <= 0) { + ticks_to_ctxt_switch = RtsFlags.ConcFlags.ctxtSwitchTicks; + context_switch = 1; /* schedule a context switch */ + } } @@ -94,32 +111,8 @@ handle_tick(int unused STG_UNUSED) #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER)) -/* - * Sigh - to avoid requiring anyone that wants to build ghc to have - * to augment the Win32 header files that comes with cygwinb20.1, - * include the missing MM API decls here inline. - * - * ToDo: check and remove these once the next version of cygwin is - * released. - */ -#define TIMERR_NOERROR 0 -#define TIMERR_NOCANDO 97 -#define TIME_PERIODIC 1 - -typedef UINT MMRESULT; -typedef void CALLBACK (*TIMECALLBACK) (UINT, UINT, DWORD, DWORD, DWORD); -typedef TIMECALLBACK *LPTIMECALLBACK; -MMRESULT STDCALL timeSetEvent(UINT, UINT, LPTIMECALLBACK, DWORD, UINT); -/* - 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; - +LPTIMECALLBACK vtalrm_cback; + nat initialize_virtual_timer(nat ms) { @@ -130,23 +123,28 @@ initialize_virtual_timer(nat ms) 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.) + (GetTickCount is used for threadDelay) */ - unsigned int delay,vtalrm_id; + unsigned int delay; + static unsigned int vtalrm_id; - delay = timeBeginPeriod(1); - if (delay == TIMERR_NOCANDO) { /* error of some sort. */ - return delay; + if (ms) { + 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 1 ms */ + vtalrm_cback, + TIME_CALLBACK_FUNCTION, /* ordinary callback */ + TIME_PERIODIC); + } else { + timeKillEvent(vtalrm_id); + timeEndPeriod(1); } - vtalrm_id = - timeSetEvent(ms, /* event every `delay' milliseconds. */ - 1, /* precision is within 5 millisecs. */ - (LPTIMECALLBACK)vtalrm_cback, - 0, - TIME_PERIODIC); # endif + return 0; } @@ -161,6 +159,9 @@ initialize_virtual_timer(nat ms) # else struct itimerval it; + timestamp = getourtimeofday(); + ticks_since_timestamp = 0; + 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; @@ -179,6 +180,9 @@ initialize_virtual_timer(nat ms) struct itimerspec it; timer_t tid; + timestamp = getourtimeofday(); + ticks_since_timestamp = 0; + se.sigev_notify = SIGEV_SIGNAL; se.sigev_signo = SIGVTALRM; se.sigev_value.sival_int = SIGVTALRM; @@ -237,12 +241,22 @@ unblock_vtalrm_signal(void) } #endif -#if !defined(HAVE_SETITIMER) && !defined(mingw32_TARGET_OS) +/* gettimeofday() takes around 1us on our 500MHz PIII. Since we're + * only calling it 50 times/s, it shouldn't have any great impact. + */ +#if !defined(mingw32_TARGET_OS) unsigned int getourtimeofday(void) { struct timeval tv; gettimeofday(&tv, (struct timezone *) NULL); - return (tv.tv_sec * 1000000 + tv.tv_usec); + return (tv.tv_sec * TICK_FREQUENCY + + tv.tv_usec * TICK_FREQUENCY / 1000000); +} +#else +unsigned int +getourtimeofday(void) +{ + return (unsigned int)GetTickCount() * 1000; } #endif