diff options
Diffstat (limited to 'rts/posix/itimer/TimerCreate.c')
-rw-r--r-- | rts/posix/itimer/TimerCreate.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/rts/posix/itimer/TimerCreate.c b/rts/posix/itimer/TimerCreate.c new file mode 100644 index 0000000000..a4fb2b5b58 --- /dev/null +++ b/rts/posix/itimer/TimerCreate.c @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------------- + * + * (c) The GHC Team, 1995-2007 + * + * Interval timer for profiling and pre-emptive scheduling. + * + * ---------------------------------------------------------------------------*/ + +#include "PosixSource.h" +#include "Rts.h" + +#include "Ticker.h" +#include "posix/Itimer.h" +#include "Proftimer.h" +#include "Schedule.h" +#include "posix/Clock.h" +#include "posix/Signals.h" + +#ifdef HAVE_SIGNAL_H +# include <signal.h> +#endif + +#include <string.h> + +static Time itimer_interval = DEFAULT_TICK_INTERVAL; +static timer_t timer; + +void +initTicker (Time interval, TickProc handle_tick) +{ + itimer_interval = interval; + + struct sigevent ev; + + // Keep programs like valgrind happy + memset(&ev, 0, sizeof(ev)); + + ev.sigev_notify = SIGEV_SIGNAL; + ev.sigev_signo = SIGVTALRM; + + if (timer_create(CLOCK_ID, &ev, &timer) != 0) { + sysErrorBelch("timer_create"); + stg_exit(EXIT_FAILURE); + } + + install_vtalrm_handler(SIGVTALRM, handle_tick); +} + +void +startTicker(void) +{ + struct itimerspec it; + + it.it_value.tv_sec = TimeToSeconds(itimer_interval); + it.it_value.tv_nsec = TimeToNS(itimer_interval) % 1000000000; + it.it_interval = it.it_value; + + if (timer_settime(timer, 0, &it, NULL) != 0) { + sysErrorBelch("timer_settime"); + stg_exit(EXIT_FAILURE); + } +} + +void +stopTicker(void) +{ + struct itimerspec it; + + it.it_value.tv_sec = 0; + it.it_value.tv_nsec = 0; + it.it_interval = it.it_value; + + if (timer_settime(timer, 0, &it, NULL) != 0) { + sysErrorBelch("timer_settime"); + stg_exit(EXIT_FAILURE); + } +} + +void +exitTicker (rtsBool wait STG_UNUSED) +{ + // Before deleting the timer set the signal to ignore to avoid the + // possibility of the signal being delivered after the timer is deleted. + signal(SIGVTALRM, SIG_IGN); + timer_delete(timer); + // ignore errors - we don't really care if it fails. +} + +int +rtsTimerSignal(void) +{ + return SIGVTALRM; +} |