summaryrefslogtreecommitdiff
path: root/rts/Timer.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-05-18 11:32:14 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-05-18 11:32:14 +0000
commitf9b4bc220a684a970a58dafa9e57d665d29b4121 (patch)
treea43e79257e8a0b159e47821b202af26c04b8b8e3 /rts/Timer.c
parent8e4fd5b3be763fc960db16deddd4efc381b815df (diff)
downloadhaskell-f9b4bc220a684a970a58dafa9e57d665d29b4121.tar.gz
Fix #4074 (I hope).
1. allow multiple threads to call startTimer()/stopTimer() pairs 2. disable the timer around fork() in forkProcess() A corresponding change to the process package is required.
Diffstat (limited to 'rts/Timer.c')
-rw-r--r--rts/Timer.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/rts/Timer.c b/rts/Timer.c
index dddc75414d..02d106fde9 100644
--- a/rts/Timer.c
+++ b/rts/Timer.c
@@ -86,6 +86,15 @@ handle_tick(int unused STG_UNUSED)
#endif
}
+// 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)
{
@@ -93,21 +102,26 @@ initTimer(void)
if (RtsFlags.MiscFlags.tickInterval != 0) {
initTicker(RtsFlags.MiscFlags.tickInterval, handle_tick);
}
+ timer_disabled = 1;
}
void
startTimer(void)
{
- if (RtsFlags.MiscFlags.tickInterval != 0) {
- startTicker();
+ if (atomic_dec(&timer_disabled) == 0) {
+ if (RtsFlags.MiscFlags.tickInterval != 0) {
+ startTicker();
+ }
}
}
void
stopTimer(void)
{
- if (RtsFlags.MiscFlags.tickInterval != 0) {
- stopTicker();
+ if (atomic_inc(&timer_disabled) == 1) {
+ if (RtsFlags.MiscFlags.tickInterval != 0) {
+ stopTicker();
+ }
}
}