struct atimer * start_atimer (enum atimer_type type, struct timespec timestamp, atimer_callback fn, void *client_data) { struct atimer *t; sigset_t oldset; /* Round TIME up to the next full second if we don't have itimers. */ #ifndef HAVE_SETITIMER if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t)) timestamp = make_timespec (timestamp.tv_sec + 1, 0); #endif /* not HAVE_SETITIMER */ /* Get an atimer structure from the free-list, or allocate a new one. */ if (free_atimers) { t = free_atimers; free_atimers = t->next; } else t = xmalloc (sizeof *t); /* Fill the atimer structure. */ memset (t, 0, sizeof *t); t->type = type; t->fn = fn; t->client_data = client_data; block_atimers (&oldset); /* Compute the timer's expiration time. */ switch (type) { case ATIMER_ABSOLUTE: t->expiration = timestamp; break; case ATIMER_RELATIVE: t->expiration = timespec_add (current_timespec (), timestamp); break; case ATIMER_CONTINUOUS: t->expiration = timespec_add (current_timespec (), timestamp); t->interval = timestamp; break; } /* Insert the timer in the list of active atimers. */ schedule_atimer (t); unblock_atimers (&oldset); /* Arrange for a SIGALRM at the time the next atimer is ripe. */ set_alarm (); return t; }
static void run_timers (void) { struct timespec now = current_timespec (); while (atimers && timespec_cmp (atimers->expiration, now) <= 0) { struct atimer *t = atimers; atimers = atimers->next; t->fn (t); if (t->type == ATIMER_CONTINUOUS) { t->expiration = timespec_add (now, t->interval); schedule_atimer (t); } else { t->next = free_atimers; free_atimers = t; } } set_alarm (); }
static char * get_time (void) { struct timespec TV2 = timespec_sub (current_timespec (), TV1); uintmax_t s = TV2.tv_sec; int ns = TV2.tv_nsec; if (watch_not_started) exit (EXIT_FAILURE); /* call reset_watch first ! */ sprintf (time_string, "%"PRIuMAX".%0*d", s, LOG10_TIMESPEC_RESOLUTION, ns); return time_string; }
static void set_alarm (void) { if (atimers) { #ifdef HAVE_SETITIMER struct itimerval it; #endif struct timespec now, interval; #ifdef HAVE_ITIMERSPEC if (0 <= timerfd || alarm_timer_ok) { struct itimerspec ispec; ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; # ifdef HAVE_TIMERFD if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) { add_timer_wait_descriptor (timerfd); return; } # endif if (alarm_timer_ok && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) return; } #endif /* Determine interval till the next timer is ripe. Don't set the interval to 0; this disables the timer. */ now = current_timespec (); interval = (timespec_cmp (atimers->expiration, now) <= 0 ? make_timespec (0, 1000 * 1000) : timespec_sub (atimers->expiration, now)); #ifdef HAVE_SETITIMER memset (&it, 0, sizeof it); it.it_value = make_timeval (interval); setitimer (ITIMER_REAL, &it, 0); #else /* not HAVE_SETITIMER */ alarm (max (interval.tv_sec, 1)); #endif /* not HAVE_SETITIMER */ } }
static void debug_timer_callback (struct atimer *t) { struct timespec now = current_timespec (); struct atimer_result *r = (struct atimer_result *) t->client_data; int result = timespec_cmp (now, r->expected); if (result < 0) /* Too early. */ r->intime = 0; else if (result >= 0) { #ifdef HAVE_SETITIMER struct timespec delta = timespec_sub (now, r->expected); /* Too late if later than expected + 0.02s. FIXME: this should depend from system clock resolution. */ if (timespec_cmp (delta, make_timespec (0, 20000000)) > 0) r->intime = 0; else #endif /* HAVE_SETITIMER */ r->intime = 1; } }
static void reset_watch (void) { TV1 = current_timespec (); watch_not_started = 0; }