[project @ 1997-01-21 08:54:45 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 # include "platform.h"
24
25 # define NON_POSIX_SOURCE
26
27 # include "rtsdefs.h"
28
29 /* As recommended in the autoconf manual */
30 # ifdef TIME_WITH_SYS_TIME
31 #  include <sys/time.h>
32 #  include <time.h>
33 # else
34 #  ifdef HAVE_SYS_TIME_H
35 #   include <sys/time.h>
36 #  else
37 #   include <time.h>
38 #  endif
39 # endif
40 \end{code}
41  
42 Handling timer events under cygwin32 is not done with signal/setitimer.
43 Instead of the two steps of first registering a signal handler to handle
44 \tr{SIGVTALRM} and then start generating them via @setitimer()@, we use
45 the Multimedia API (MM) and its @timeSetEvent@. (Internally, the MM API
46 creates a separate thread that will notify the main thread of timer
47 expiry). -- SOF 7/96
48
49 \begin{code}
50 #if defined(cygwin32_TARGET_OS)
51
52 #include <windows.h>  /* OK, bring it all in... */
53
54 /*
55   vtalrm_handler is assigned and set up in
56   main/Signals.lc.
57
58   vtalrm_id (defined in main/Signals.lc) holds
59   the system id for the current timer (used to 
60   later block/kill the timer)
61 */
62 extern I_ vtalrm_id;
63 extern TIMECALLBACK *vtalrm_cback;
64  
65 int 
66 initialize_virtual_timer(ms)
67 int ms;
68 {
69   /* VTALRM is currently not supported by  cygwin32, 
70      so we use the Timer support provided by the
71      MultiMedia API that is part of Win32. The
72      parameters to timeSetEvent may require some tweaking.
73   */
74   unsigned int delay,vtalrm_id;
75  
76   delay = timeBeginPeriod(1);
77   if (delay == TIMERR_NOCANDO) { /* error of some sort. */
78      return delay;
79   }
80   vtalrm_id =
81     timeSetEvent(ms,     /* event every `delay' milliseconds. */
82                 1,       /* precision is within 5 millisecs. */
83                 (LPTIMECALLBACK)vtalrm_cback,
84                 0,
85                 TIME_PERIODIC);
86   return 0;
87 }
88  
89 #else
90
91 int
92 initialize_virtual_timer(ms)
93 int ms;
94 {
95 # ifndef HAVE_SETITIMER
96     fprintf(stderr, "No virtual timer on this system\n");
97     return -1;
98 # else
99     struct itimerval it;
100
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));
105 # endif
106 }
107
108 #endif /* !cygwin32_TARGET_OS */
109
110 # if 0
111 /* This is a potential POSIX version */
112 int
113 initialize_virtual_timer(ms)
114 int ms;
115 {
116     struct sigevent se;
117     struct itimerspec it;
118     timer_t tid;
119
120     se.sigev_notify = SIGEV_SIGNAL;
121     se.sigev_signo = SIGVTALRM;
122     se.sigev_value.sival_int = SIGVTALRM;
123     if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
124         fprintf(stderr, "Can't create virtual timer.\n");
125         EXIT(EXIT_FAILURE);
126     }
127     it.it_value.tv_sec = ms / 1000;
128     it.it_value.tv_nsec = 1000000 * (ms - 1000 * it.it_value.tv_sec);
129     it.it_interval = it.it_value;
130     timer_settime(tid, TIMER_RELTIME, &it, NULL);
131 }
132 # endif
133
134 #endif  /* PROFILING || CONCURRENT */
135
136 \end{code}