X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FTimer.c;h=02d106fde9a2553f2f2fa10930df0f0869170921;hb=26f4bfc82f2b2359259578e9c54d476fc2de650f;hp=0bfea2d6fd9236224c1bec0e359874a9f497d2e1;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/rts/Timer.c b/rts/Timer.c index 0bfea2d..02d106f 100644 --- a/rts/Timer.c +++ b/rts/Timer.c @@ -14,13 +14,16 @@ * on platform-specific services to install and run the timers. * */ + +#include "PosixSource.h" #include "Rts.h" -#include "RtsFlags.h" + +#include "Timer.h" #include "Proftimer.h" #include "Schedule.h" -#include "Timer.h" #include "Ticker.h" #include "Capability.h" +#include "RtsSignals.h" /* ticks left before next pre-emptive context switch */ static int ticks_to_ctxt_switch = 0; @@ -40,43 +43,41 @@ static void handle_tick(int unused STG_UNUSED) { -#ifdef PROFILING handleProfTick(); -#endif if (RtsFlags.ConcFlags.ctxtSwitchTicks > 0) { ticks_to_ctxt_switch--; if (ticks_to_ctxt_switch <= 0) { ticks_to_ctxt_switch = RtsFlags.ConcFlags.ctxtSwitchTicks; - context_switch = 1; /* schedule a context switch */ + setContextSwitches(); /* schedule a context switch */ } } #if defined(THREADED_RTS) /* - * If we've been inactive for idleGCDelayTicks (set by +RTS + * If we've been inactive for idleGCDelayTime (set by +RTS * -I), tell the scheduler to wake up and do a GC, to check * for threads that are deadlocked. */ switch (recent_activity) { case ACTIVITY_YES: recent_activity = ACTIVITY_MAYBE_NO; - ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTicks; + ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime / + RtsFlags.MiscFlags.tickInterval; break; case ACTIVITY_MAYBE_NO: - if (ticks_to_gc == 0) break; /* 0 ==> no idle GC */ - ticks_to_gc--; if (ticks_to_gc == 0) { - ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTicks; - recent_activity = ACTIVITY_INACTIVE; - blackholes_need_checking = rtsTrue; - /* hack: re-use the blackholes_need_checking flag */ - - /* ToDo: this doesn't work. Can't invoke - * pthread_cond_signal from a signal handler. - * Furthermore, we can't prod a capability that we - * might be holding. What can we do? - */ - prodOneCapability(); + /* 0 ==> no idle GC */ + recent_activity = ACTIVITY_DONE_GC; + // disable timer signals (see #1623) + stopTimer(); + } else { + ticks_to_gc--; + if (ticks_to_gc == 0) { + ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime / + RtsFlags.MiscFlags.tickInterval; + recent_activity = ACTIVITY_INACTIVE; + wakeUpRts(); + } } break; default: @@ -85,18 +86,49 @@ handle_tick(int unused STG_UNUSED) #endif } -int -startTimer(nat ms) +// This global counter is used to allow multiple threads to stop the +// timer temporarily with a stopTimer()/startTimer() pair. If +// timer_enabled == 0 timer is enabled +// timer_disabled == N, N > 0 timer is disabled by N threads +// When timer_enabled makes a transition to 0, we enable the timer, +// and when it makes a transition to non-0 we disable it. + +static StgWord timer_disabled; + +void +initTimer(void) { -#ifdef PROFILING - initProfTimer(); -#endif + initProfTimer(); + if (RtsFlags.MiscFlags.tickInterval != 0) { + initTicker(RtsFlags.MiscFlags.tickInterval, handle_tick); + } + timer_disabled = 1; +} + +void +startTimer(void) +{ + if (atomic_dec(&timer_disabled) == 0) { + if (RtsFlags.MiscFlags.tickInterval != 0) { + startTicker(); + } + } +} - return startTicker(ms, handle_tick); +void +stopTimer(void) +{ + if (atomic_inc(&timer_disabled) == 1) { + if (RtsFlags.MiscFlags.tickInterval != 0) { + stopTicker(); + } + } } -int -stopTimer() +void +exitTimer (rtsBool wait) { - return stopTicker(); + if (RtsFlags.MiscFlags.tickInterval != 0) { + exitTicker(wait); + } }