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