+ * Copyright (C) 1990 Don Libes
+ * Copyright (C) 2015 Renato L. F. Cunha
+ * An implementation of an arbitrary set of timers that use a single "real"
+ * timer (with the alarm function, in this case).
+ * This implementation most completely based on Don Libes' notes found at
+ * http://www.kohala.com/start/libes.timers.txt - The only things I changed
+ * were that I actually used a timer, and actually implemented signal
+static sigset_t oldset; /* < backup storage for the old signal mask */
+static TIME time_timer_set, time_now; /* < internal timers */
+static struct timer *timer_next = NULL; /* < the next timer that might be fired */
+static void sig_alarm();
+static void timers_update(TIME);
+ * Disables interrupts by blocking all signals with a call to sigprocmask.
+static void disable_interrupts() {
+ sigprocmask(SIG_BLOCK, &set, &oldset);
+ * Re-enables interrupts by restoring the original signal mask.
+static void enable_interrupts() {
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ * The original document suggests the current time can be a volatile variable
+ * that's updated by some other thread, or by the OS, whatever. We don't have
+ * it here, so, every time we have to read the current time, we must call this
+ * function to update our internal clock.
+static inline void update_time_now() {
+ clock_gettime(CLOCK_REALTIME, &tp);
+ * Starts the "physical" timer by calling alarm(time).
+static void start_physical_timer(TIME time) {
+ if (signal(SIGALRM, sig_alarm) == SIG_ERR) {
+ fprintf(stderr, "Can't catch SIGALRM\n");
+ * The original timer interrupt handler. Updates the current time, updates all
+ * timers and, if there is a timer to expire in the future, re-starts the
+ * "physical" timer to the closest possible.
+static inline void timer_interrupt_handler() {
+ timers_update(time_now - time_timer_set);
+ /* start physical timer for next shortest time if one exists */
+ time_timer_set = time_now;
+ start_physical_timer(timer_next->time);
+ * Just a handler to SIGALRM.
+static void sig_alarm(int signo) {
+ timer_interrupt_handler();
+ * "Constructor". Initializes the set of timers.
+ for (t = timers; t < &timers[MAX_TIMERS]; t++) {
+static void timers_update(TIME time) {
+ static struct timer timer_last = { /* This is just a placeholder */
+ VERY_LONG_TIME, /* time */
+ NULL /* event pointer */
+ timer_next = &timer_last;
+ for (t=timers; t < &timers[MAX_TIMERS]; t++) {
+ if (time < t->time) { /* haven't expired yet */
+ if (t->time < timer_next->time) {
+ * FIXME: Add a callback functionality to invoke
+ t->inuse = 0; /* remove timer, since it is done */
+ if (!timer_next->inuse) {
+ * Declares a new timer.
+ * time -> In this many seconds the timer must go off
+ * event -> Will be set to true when this timer does expire
+ * Returns a pointer to the newly created timer.
+struct timer *timer_declare(unsigned int time, char *event) {
+ for (t=timers; t < &timers[MAX_TIMERS]; t++) {
+ if (t == &timers[MAX_TIMERS]) {
+ /* install new timer */
+ /* no timers, this is the shortest */
+ time_timer_set = time_now;
+ start_physical_timer((timer_next = t)->time);
+ } else if ((time + time_now) < (timer_next->time + time_timer_set)) {
+ /* new timer is shorter than current one, so update it */
+ timers_update(time_now - time_timer_set);
+ time_timer_set = time_now;
+ start_physical_timer((timer_next = t)->time);
+ * Deallocates a timer returned by timer_declare.
+void timer_undeclare(struct timer *t) {
+ /* check if we were waiting on this one */
+ timers_update(time_now - time_timer_set);
+ start_physical_timer(timer_next->time);
+ time_timer_set = time_now;