/* ----------------------------------------------------------------------------- * * (c) The GHC Team, 1995-2007 * * Interval timer for profiling and pre-emptive scheduling. * * ---------------------------------------------------------------------------*/ #include "PosixSource.h" #include "Rts.h" #include "Ticker.h" #include "Proftimer.h" #include "Schedule.h" #include "posix/Clock.h" #include "posix/Signals.h" #if defined(HAVE_SIGNAL_H) # include #endif #include 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 (bool 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; }