1 /* -----------------------------------------------------------------------------
2 * $Id: Itimer.c,v 1.4 1999/03/03 19:00:07 sof 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
28 /* As recommended in the autoconf manual */
29 # ifdef TIME_WITH_SYS_TIME
30 # include <sys/time.h>
33 # ifdef HAVE_SYS_TIME_H
34 # include <sys/time.h>
45 * Handling timer events under cygwin32 is not done with signal/setitimer.
46 * Instead of the two steps of first registering a signal handler to handle
47 * \tr{SIGVTALRM} and then start generating them via @setitimer()@, we use
48 * the Multimedia API (MM) and its @timeSetEvent@. (Internally, the MM API
49 * creates a separate thread that will notify the main thread of timer
50 * expiry). -- SOF 7/96
52 * 11/98: if the cygwin DLL supports setitimer(), then use it instead.
55 #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER))
58 vtalrm_handler is assigned and set up in Signals.c
60 vtalrm_id (defined in Signals.c) holds
61 the system id for the current timer (used to
65 TIMECALLBACK *vtalrm_cback;
68 initialize_virtual_timer(nat ms)
70 /* VTALRM is currently not supported by cygwin32,
71 so we use the Timer support provided by the
72 MultiMedia API that is part of Win32. The
73 parameters to timeSetEvent may require some tweaking.
75 unsigned int delay,vtalrm_id;
77 delay = timeBeginPeriod(1);
78 if (delay == TIMERR_NOCANDO) { /* error of some sort. */
82 timeSetEvent(ms, /* event every `delay' milliseconds. */
83 1, /* precision is within 5 millisecs. */
84 (LPTIMECALLBACK)vtalrm_cback,
93 initialize_virtual_timer(nat ms)
95 # ifndef HAVE_SETITIMER
96 fprintf(stderr, "No virtual timer on this system\n");
101 it.it_value.tv_sec = ms / 1000;
102 it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec));
103 it.it_interval = it.it_value;
104 return (setitimer(ITIMER_VIRTUAL, &it, NULL));
108 #endif /* !cygwin32_TARGET_OS */
111 /* This is a potential POSIX version */
113 initialize_virtual_timer(nat ms)
116 struct itimerspec it;
119 se.sigev_notify = SIGEV_SIGNAL;
120 se.sigev_signo = SIGVTALRM;
121 se.sigev_value.sival_int = SIGVTALRM;
122 if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
123 fprintf(stderr, "Can't create virtual timer.\n");
126 it.it_value.tv_sec = ms / 1000;
127 it.it_value.tv_nsec = 1000000 * (ms - 1000 * it.it_value.tv_sec);
128 it.it_interval = it.it_value;
129 timer_settime(tid, TIMER_RELTIME, &it, NULL);
133 #if defined(mingw32_TARGET_OS) || (defined(cygwin32_TARGET_OS) && !defined(HAVE_SETITIMER))
135 install_vtalrm_handler(void (*handler)(int))
137 vtalrm_cback = handler;
143 install_vtalrm_handler(void (*handler)(int))
145 struct sigaction action;
147 action.sa_handler = handler;
149 sigemptyset(&action.sa_mask);
152 return sigaction(SIGVTALRM, &action, NULL);
156 block_vtalrm_signal(void)
160 sigemptyset(&signals);
161 sigaddset(&signals, SIGVTALRM);
163 (void) sigprocmask(SIG_BLOCK, &signals, NULL);
167 unblock_vtalrm_signal(void)
171 sigemptyset(&signals);
172 sigaddset(&signals, SIGVTALRM);
174 (void) sigprocmask(SIG_UNBLOCK, &signals, NULL);