1 /* -----------------------------------------------------------------------------
2 * $Id: Itimer.c,v 1.15 2000/07/17 15:09:35 rrt Exp $
4 * (c) The GHC Team, 1995-1999
6 * Interval timer for profiling and pre-emptive scheduling.
8 * ---------------------------------------------------------------------------*/
11 * The interval timer is used for profiling and for context switching in the
12 * threaded build. Though POSIX 1003.1b includes a standard interface for
13 * such things, no one really seems to be implementing them yet. Even
14 * Solaris 2.3 only seems to provide support for @CLOCK_REAL@, whereas we're
15 * keen on getting access to @CLOCK_VIRTUAL@.
17 * Hence, we use the old-fashioned @setitimer@ that just about everyone seems
18 * to support. So much for standards.
22 # define NON_POSIX_SOURCE
27 #include "Proftimer.h"
30 /* As recommended in the autoconf manual */
31 # ifdef TIME_WITH_SYS_TIME
32 # include <sys/time.h>
35 # ifdef HAVE_SYS_TIME_H
36 # include <sys/time.h>
50 #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER))
53 handle_tick(int unused STG_UNUSED);
55 /* -----------------------------------------------------------------------------
58 We use the ticker for two things: supporting threadDelay, and time
61 SMP note: this signal could be delivered to *any* thread. We have
62 to ensure that it doesn't matter which thread actually runs the
64 -------------------------------------------------------------------------- */
68 #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER))
71 handle_tick(int unused STG_UNUSED)
79 /* For threadDelay etc., see Select.c */
87 * Handling timer events under cygwin32 is not done with signal/setitimer.
88 * Instead of the two steps of first registering a signal handler to handle
89 * \tr{SIGVTALRM} and then start generating them via @setitimer()@, we use
90 * the Multimedia API (MM) and its @timeSetEvent@. (Internally, the MM API
91 * creates a separate thread that will notify the main thread of timer
92 * expiry). -- SOF 7/96
94 * 11/98: if the cygwin DLL supports setitimer(), then use it instead.
97 #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER))
100 vtalrm_handler is assigned and set up in Signals.c
102 vtalrm_id (defined in Signals.c) holds
103 the system id for the current timer (used to
104 later block/kill it.)
106 extern nat vtalrm_id;
107 TIMECALLBACK *vtalrm_cback;
110 initialize_virtual_timer(nat ms)
113 /* On Win32 setups that don't have support for
114 setitimer(), we use the MultiMedia API's timer
117 As the delivery of ticks isn't free, we only
118 enable it if we really needed, i.e., when profiling.
119 (the RTS now also needs timer ticks to implement
120 threadDelay in non-profiling mode, but the pure
121 Win32 port doesn't support that.....yet.)
123 unsigned int delay,vtalrm_id;
125 delay = timeBeginPeriod(1);
126 if (delay == TIMERR_NOCANDO) { /* error of some sort. */
130 timeSetEvent(ms, /* event every `delay' milliseconds. */
131 1, /* precision is within 5 millisecs. */
132 (LPTIMECALLBACK)vtalrm_cback,
142 initialize_virtual_timer(nat ms)
144 # ifndef HAVE_SETITIMER
145 /* fprintf(stderr, "No virtual timer on this system\n"); */
150 it.it_value.tv_sec = ms / 1000;
151 it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec));
152 it.it_interval = it.it_value;
153 return (setitimer(ITIMER_VIRTUAL, &it, NULL));
157 #endif /* !cygwin32_TARGET_OS */
160 /* This is a potential POSIX version */
162 initialize_virtual_timer(nat ms)
165 struct itimerspec it;
168 se.sigev_notify = SIGEV_SIGNAL;
169 se.sigev_signo = SIGVTALRM;
170 se.sigev_value.sival_int = SIGVTALRM;
171 if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
172 barf("can't create virtual timer");
174 it.it_value.tv_sec = ms / 1000;
175 it.it_value.tv_nsec = 1000000 * (ms - 1000 * it.it_value.tv_sec);
176 it.it_interval = it.it_value;
177 timer_settime(tid, TIMER_RELTIME, &it, NULL);
181 #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER))
183 install_vtalrm_handler(void)
185 vtalrm_cback = handle_tick;
191 install_vtalrm_handler(void)
193 struct sigaction action;
195 action.sa_handler = handle_tick;
197 sigemptyset(&action.sa_mask);
200 return sigaction(SIGVTALRM, &action, NULL);
204 block_vtalrm_signal(void)
208 sigemptyset(&signals);
209 sigaddset(&signals, SIGVTALRM);
211 (void) sigprocmask(SIG_BLOCK, &signals, NULL);
215 unblock_vtalrm_signal(void)
219 sigemptyset(&signals);
220 sigaddset(&signals, SIGVTALRM);
222 (void) sigprocmask(SIG_UNBLOCK, &signals, NULL);
226 #if !defined(HAVE_SETITIMER) && !defined(mingw32_TARGET_OS)
228 getourtimeofday(void)
231 gettimeofday(&tv, (struct timezone *) NULL);
232 return (tv.tv_sec * 1000000 + tv.tv_usec);