[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / runtime / main / Itimer.lc
1 %
2 % (c) The AQUA Project, Glasgow University, 1995
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[Itimer.lc]{Interval Timer}
7 %*                                                                      *
8 %************************************************************************
9
10 The interval timer is used for profiling and for context switching in the
11 threaded build.  Though POSIX 1003.1b includes a standard interface for
12 such things, no one really seems to be implementing them yet.  Even 
13 Solaris 2.3 only seems to provide support for @CLOCK_REAL@, whereas we're
14 keen on getting access to @CLOCK_VIRTUAL@.
15
16 Hence, we use the old-fashioned @setitimer@ that just about everyone seems
17 to support.  So much for standards.
18
19 \begin{code}
20
21 #if defined(PROFILING) || defined(CONCURRENT)
22
23 /* OLD: # include "platform.h" */
24
25 # include "config.h"
26
27 #if !defined(_AIX)
28 # define NON_POSIX_SOURCE
29 #endif
30
31 # include "rtsdefs.h"
32
33 /* As recommended in the autoconf manual */
34 # ifdef TIME_WITH_SYS_TIME
35 #  include <sys/time.h>
36 #  include <time.h>
37 # else
38 #  ifdef HAVE_SYS_TIME_H
39 #   include <sys/time.h>
40 #  else
41 #   include <time.h>
42 #  endif
43 # endif
44 \end{code}
45  
46 Handling timer events under cygwin32 is not done with signal/setitimer.
47 Instead of the two steps of first registering a signal handler to handle
48 \tr{SIGVTALRM} and then start generating them via @setitimer()@, we use
49 the Multimedia API (MM) and its @timeSetEvent@. (Internally, the MM API
50 creates a separate thread that will notify the main thread of timer
51 expiry). -- SOF 7/96
52
53 \begin{code}
54 #if defined(cygwin32_TARGET_OS)
55
56 #include <windows.h>  /* OK, bring it all in... */
57
58 /*
59   vtalrm_handler is assigned and set up in
60   main/Signals.lc.
61
62   vtalrm_id (defined in main/Signals.lc) holds
63   the system id for the current timer (used to 
64   later block/kill the timer)
65 */
66 extern I_ vtalrm_id;
67 extern TIMECALLBACK *vtalrm_cback;
68  
69 int 
70 initialize_virtual_timer(ms)
71 int ms;
72 {
73   /* VTALRM is currently not supported by  cygwin32, 
74      so we use the Timer support provided by the
75      MultiMedia API that is part of Win32. The
76      parameters to timeSetEvent may require some tweaking.
77   */
78   unsigned int delay,vtalrm_id;
79  
80   delay = timeBeginPeriod(1);
81   if (delay == TIMERR_NOCANDO) { /* error of some sort. */
82      return delay;
83   }
84   vtalrm_id =
85     timeSetEvent(ms,     /* event every `delay' milliseconds. */
86                 1,       /* precision is within 5 millisecs. */
87                 (LPTIMECALLBACK)vtalrm_cback,
88                 0,
89                 TIME_PERIODIC);
90   return 0;
91 }
92  
93 #else
94
95 int
96 initialize_virtual_timer(ms)
97 int ms;
98 {
99 # ifndef HAVE_SETITIMER
100     fprintf(stderr, "No virtual timer on this system\n");
101     return -1;
102 # else
103     struct itimerval it;
104
105     it.it_value.tv_sec = ms / 1000;
106     it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec));
107     it.it_interval = it.it_value;
108     return (setitimer(ITIMER_VIRTUAL, &it, NULL));
109 # endif
110 }
111
112 #endif /* !cygwin32_TARGET_OS */
113
114 # if 0
115 /* This is a potential POSIX version */
116 int
117 initialize_virtual_timer(ms)
118 int ms;
119 {
120     struct sigevent se;
121     struct itimerspec it;
122     timer_t tid;
123
124     se.sigev_notify = SIGEV_SIGNAL;
125     se.sigev_signo = SIGVTALRM;
126     se.sigev_value.sival_int = SIGVTALRM;
127     if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
128         fprintf(stderr, "Can't create virtual timer.\n");
129         EXIT(EXIT_FAILURE);
130     }
131     it.it_value.tv_sec = ms / 1000;
132     it.it_value.tv_nsec = 1000000 * (ms - 1000 * it.it_value.tv_sec);
133     it.it_interval = it.it_value;
134     timer_settime(tid, TIMER_RELTIME, &it, NULL);
135 }
136 # endif
137
138 #endif  /* PROFILING || CONCURRENT */
139
140 \end{code}