diff options
author | Simon Marlow <marlowsd@gmail.com> | 2011-11-25 13:11:39 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2011-11-25 16:11:36 +0000 |
commit | 6b1098511aaabd2c9503ee7be6da1944466f9cb4 (patch) | |
tree | 83b3001603c7e6a5cfb3ac04adbb99c40504942e /rts/posix/Select.c | |
parent | 18aae18503442276e14a47eabf4786bc7210662e (diff) | |
download | haskell-6b1098511aaabd2c9503ee7be6da1944466f9cb4.tar.gz |
Time handling overhaul
Terminology cleanup: the type "Ticks" has been renamed "Time", which
is an StgWord64 in units of TIME_RESOLUTION (currently nanoseconds).
The terminology "tick" is now used consistently to mean the interval
between timer signals.
The ticker now always ticks in realtime (actually CLOCK_MONOTONIC if
we have it). Before it used CPU time in the non-threaded RTS and
realtime in the threaded RTS, but I've discovered that the CPU timer
has terrible resolution (at least on Linux) and isn't much use for
profiling. So now we always use realtime. This should also fix
The default tick interval is now 10ms, except when profiling where we
drop it to 1ms. This gives more accurate profiles without affecting
runtime too much (<1%).
Lots of cleanups - the resolution of Time is now in one place
only (Rts.h) rather than having calculations that depend on the
resolution scattered all over the RTS. I hope I found them all.
Diffstat (limited to 'rts/posix/Select.c')
-rw-r--r-- | rts/posix/Select.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/rts/posix/Select.c b/rts/posix/Select.c index 3c87fbdc70..45737ce0cc 100644 --- a/rts/posix/Select.c +++ b/rts/posix/Select.c @@ -16,6 +16,7 @@ #include "Capability.h" #include "Select.h" #include "AwaitEvent.h" +#include "Stats.h" # ifdef HAVE_SYS_SELECT_H # include <sys/select.h> @@ -37,13 +38,24 @@ #endif #if !defined(THREADED_RTS) -/* last timestamp */ -lnat timestamp = 0; /* * The threaded RTS uses an IO-manager thread in Haskell instead (see GHC.Conc) */ +#define LowResTimeToTime(t) (USToTime((t) * 10000)) + +/* + * Return the time since the program started, in LowResTime, + * rounded down. + * + * This is only used by posix/Select.c. It should probably go away. + */ +LowResTime getourtimeofday(void) +{ + return TimeToUS(stat_getElapsedTime()) / 10000; +} + /* There's a clever trick here to avoid problems when the time wraps * around. Since our maximum delay is smaller than 31 bits of ticks * (it's actually 31 bits of microseconds), we can safely check @@ -55,15 +67,14 @@ lnat timestamp = 0; * if this is true, then our time has expired. * (idea due to Andy Gill). */ -static rtsBool -wakeUpSleepingThreads(lnat ticks) +static rtsBool wakeUpSleepingThreads (LowResTime now) { StgTSO *tso; rtsBool flag = rtsFalse; while (sleeping_queue != END_TSO_QUEUE) { tso = sleeping_queue; - if (((long)ticks - (long)tso->block_info.target) < 0) { + if (((long)now - (long)tso->block_info.target) < 0) { break; } sleeping_queue = tso->_link; @@ -108,7 +119,8 @@ awaitEvent(rtsBool wait) rtsBool select_succeeded = rtsTrue; rtsBool unblock_all = rtsFalse; struct timeval tv; - lnat min, ticks; + Time min; + LowResTime now; tv.tv_sec = 0; tv.tv_usec = 0; @@ -128,18 +140,17 @@ awaitEvent(rtsBool wait) */ do { - ticks = timestamp = getourtimeofday(); - if (wakeUpSleepingThreads(ticks)) { + now = getourtimeofday(); + if (wakeUpSleepingThreads(now)) { return; } if (!wait) { min = 0; } else if (sleeping_queue != END_TSO_QUEUE) { - min = (sleeping_queue->block_info.target - ticks) - * RtsFlags.MiscFlags.tickInterval * 1000; + min = LowResTimeToTime(sleeping_queue->block_info.target - now); } else { - min = 0x7ffffff; + min = (Time)-1; } /* @@ -185,8 +196,8 @@ awaitEvent(rtsBool wait) /* Check for any interesting events */ - tv.tv_sec = min / 1000000; - tv.tv_usec = min % 1000000; + tv.tv_sec = TimeToSeconds(min); + tv.tv_usec = TimeToUS(min) % 1000000; while ((numFound = select(maxfd+1, &rfd, &wfd, NULL, &tv)) < 0) { if (errno != EINTR) { @@ -236,7 +247,7 @@ awaitEvent(rtsBool wait) /* check for threads that need waking up */ - wakeUpSleepingThreads(getourtimeofday()); + wakeUpSleepingThreads(getourtimeofday()); /* If new runnable threads have arrived, stop waiting for * I/O and run them. |