struct atimer * start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn, void *client_data) { struct atimer *t; /* Round TIME up to the next full second if we don't have itimers. */ #ifndef HAVE_SETITIMER if (EMACS_NSECS (timestamp) != 0 && EMACS_SECS (timestamp) < TYPE_MAXIMUM (time_t)) timestamp = make_emacs_time (EMACS_SECS (timestamp) + 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 (); /* Compute the timer's expiration time. */ switch (type) { case ATIMER_ABSOLUTE: t->expiration = timestamp; break; case ATIMER_RELATIVE: t->expiration = add_emacs_time (current_emacs_time (), timestamp); break; case ATIMER_CONTINUOUS: t->expiration = add_emacs_time (current_emacs_time (), timestamp); t->interval = timestamp; break; } /* Insert the timer in the list of active atimers. */ schedule_atimer (t); unblock_atimers (); /* Arrange for a SIGALRM at the time the next atimer is ripe. */ set_alarm (); return t; }
static void run_timers (void) { EMACS_TIME now = current_emacs_time (); while (atimers && EMACS_TIME_LE (atimers->expiration, now)) { struct atimer *t = atimers; atimers = atimers->next; t->fn (t); if (t->type == ATIMER_CONTINUOUS) { t->expiration = add_emacs_time (now, t->interval); schedule_atimer (t); } else { t->next = free_atimers; free_atimers = t; } } set_alarm (); }
static char * get_time (void) { EMACS_TIME TV2 = sub_emacs_time (current_emacs_time (), TV1); uintmax_t s = EMACS_SECS (TV2); int ns = EMACS_NSECS (TV2); if (watch_not_started) exit (EXIT_FAILURE); /* call reset_watch first ! */ sprintf (time_string, "%"PRIuMAX".%0*d", s, LOG10_EMACS_TIME_RESOLUTION, ns); return time_string; }
static void set_alarm (void) { if (atimers) { #ifdef HAVE_SETITIMER struct itimerval it; #endif EMACS_TIME now, interval; #ifdef HAVE_ITIMERSPEC if (alarm_timer_ok) { struct itimerspec ispec; ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; if (timer_settime (alarm_timer, 0, &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_emacs_time (); interval = (EMACS_TIME_LE (atimers->expiration, now) ? make_emacs_time (0, 1000 * 1000) : sub_emacs_time (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 (EMACS_SECS (interval), 1)); #endif /* not HAVE_SETITIMER */ } }
static void reset_watch (void) { TV1 = current_emacs_time (); watch_not_started = 0; }