Itimer.lc 3.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
%
% (c) The AQUA Project, Glasgow University, 1995
%
%************************************************************************
%*                                                                      *
\section[Itimer.lc]{Interval Timer}
%*									*
%************************************************************************

The interval timer is used for profiling and for context switching in the
sof's avatar
sof committed
11
threaded build.  Though POSIX 1003.1b includes a standard interface for
12 13 14 15 16 17 18 19 20
such things, no one really seems to be implementing them yet.  Even 
Solaris 2.3 only seems to provide support for @CLOCK_REAL@, whereas we're
keen on getting access to @CLOCK_VIRTUAL@.

Hence, we use the old-fashioned @setitimer@ that just about everyone seems
to support.  So much for standards.

\begin{code}

21
#if defined(PROFILING) || defined(CONCURRENT)
22

sof's avatar
sof committed
23 24 25
/* OLD: # include "platform.h" */

# include "config.h"
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

# define NON_POSIX_SOURCE

# include "rtsdefs.h"

/* As recommended in the autoconf manual */
# ifdef TIME_WITH_SYS_TIME
#  include <sys/time.h>
#  include <time.h>
# else
#  ifdef HAVE_SYS_TIME_H
#   include <sys/time.h>
#  else
#   include <time.h>
#  endif
# endif
sof's avatar
sof committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
\end{code}
 
Handling timer events under cygwin32 is not done with signal/setitimer.
Instead of the two steps of first registering a signal handler to handle
\tr{SIGVTALRM} and then start generating them via @setitimer()@, we use
the Multimedia API (MM) and its @timeSetEvent@. (Internally, the MM API
creates a separate thread that will notify the main thread of timer
expiry). -- SOF 7/96

\begin{code}
#if defined(cygwin32_TARGET_OS)

#include <windows.h>  /* OK, bring it all in... */

/*
  vtalrm_handler is assigned and set up in
  main/Signals.lc.

  vtalrm_id (defined in main/Signals.lc) holds
  the system id for the current timer (used to 
  later block/kill the timer)
*/
extern I_ vtalrm_id;
extern TIMECALLBACK *vtalrm_cback;
 
int 
initialize_virtual_timer(ms)
int ms;
{
  /* VTALRM is currently not supported by  cygwin32, 
     so we use the Timer support provided by the
     MultiMedia API that is part of Win32. The
     parameters to timeSetEvent may require some tweaking.
  */
  unsigned int delay,vtalrm_id;
 
  delay = timeBeginPeriod(1);
  if (delay == TIMERR_NOCANDO) { /* error of some sort. */
     return delay;
  }
  vtalrm_id =
    timeSetEvent(ms,     /* event every `delay' milliseconds. */
 	        1,       /* precision is within 5 millisecs. */
 	        (LPTIMECALLBACK)vtalrm_cback,
 		0,
 		TIME_PERIODIC);
  return 0;
}
 
#else
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

int
initialize_virtual_timer(ms)
int ms;
{
# ifndef HAVE_SETITIMER
    fprintf(stderr, "No virtual timer on this system\n");
    return -1;
# else
    struct itimerval it;

    it.it_value.tv_sec = ms / 1000;
    it.it_value.tv_usec = 1000 * (ms - (1000 * it.it_value.tv_sec));
    it.it_interval = it.it_value;
    return (setitimer(ITIMER_VIRTUAL, &it, NULL));
# endif
}

sof's avatar
sof committed
110 111
#endif /* !cygwin32_TARGET_OS */

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
# if 0
/* This is a potential POSIX version */
int
initialize_virtual_timer(ms)
int ms;
{
    struct sigevent se;
    struct itimerspec it;
    timer_t tid;

    se.sigev_notify = SIGEV_SIGNAL;
    se.sigev_signo = SIGVTALRM;
    se.sigev_value.sival_int = SIGVTALRM;
    if (timer_create(CLOCK_VIRTUAL, &se, &tid)) {
	fprintf(stderr, "Can't create virtual timer.\n");
	EXIT(EXIT_FAILURE);
    }
    it.it_value.tv_sec = ms / 1000;
    it.it_value.tv_nsec = 1000000 * (ms - 1000 * it.it_value.tv_sec);
    it.it_interval = it.it_value;
    timer_settime(tid, TIMER_RELTIME, &it, NULL);
}
# endif

136
#endif	/* PROFILING || CONCURRENT */
137 138

\end{code}