blob: f66463015d36b04f4195d64435a2281e35e73ccf [file] [log] [blame] [edit]
/* Copyright (c) 2013 The Regents of the University of California
* Barret Rhoden <brho@cs.berkeley.edu>
* See LICENSE for details.
*
* Userspace alarm service, based off a slimmed down version of the kernel
* alarms. Under the hood, it uses the kernel alarm service for the root of
* the alarm chain.
*
* This is (was) hanging out in benchutil so as to not create a dependency from
* parlib on benchutil (usec2tsc and friends).
*
* There's only one timer chain, unlike in the kernel, for the entire process.
* If you want one-off timers unrelated to the chain (and sent to other vcores),
* use #A directly.
*
* Your handlers will run from vcore context.
*
* 1) To set a handler to run on an alarm:
* struct alarm_waiter *waiter = malloc(sizeof(struct alarm_waiter));
* init_awaiter(waiter, HANDLER);
* waiter->data = something;
* set_awaiter_rel(waiter, USEC);
* set_alarm(waiter);
* If you want the HANDLER to run again, do this at the end of it:
* set_awaiter_rel(waiter, USEC);
* __set_alarm(waiter);
* Do not call set_alarm() from within an alarm handler; you'll deadlock.
* Don't forget to manage your memory at some (safe) point:
* free(waiter); */
#ifndef _ALARM_H
#define _ALARM_H
#include <ros/common.h>
#include <sys/queue.h>
#include <spinlock.h>
#include <event.h>
/* Specifc waiter, per alarm */
struct alarm_waiter {
uint64_t wake_up_time; /* tsc time */
void (*func) (struct alarm_waiter *waiter);
void *data;
TAILQ_ENTRY(alarm_waiter) next;
bool on_tchain;
};
TAILQ_HEAD(awaiters_tailq, alarm_waiter); /* ideally not a LL */
typedef void (*alarm_handler)(struct alarm_waiter *waiter);
/* Sorted collection of alarms. */
struct timer_chain {
struct spin_pdr_lock lock;
struct awaiters_tailq waiters;
uint64_t earliest_time;
uint64_t latest_time;
int ctlfd;
int timerfd;
int alarmid;
struct event_queue *ev_q;
};
/* For fresh alarm waiters. func == 0 for kthreads */
void init_awaiter(struct alarm_waiter *waiter,
void (*func) (struct alarm_waiter *));
/* Sets the time an awaiter goes off */
void set_awaiter_abs(struct alarm_waiter *waiter, uint64_t abs_time);
void set_awaiter_abs_unix(struct alarm_waiter *waiter, uint64_t abs_time);
void set_awaiter_rel(struct alarm_waiter *waiter, uint64_t usleep);
void set_awaiter_inc(struct alarm_waiter *waiter, uint64_t usleep);
/* Arms/disarms the alarm */
void __set_alarm(struct alarm_waiter *waiter);
void set_alarm(struct alarm_waiter *waiter);
bool unset_alarm(struct alarm_waiter *waiter);
void reset_alarm_abs(struct alarm_waiter *waiter, uint64_t abs_time);
/* "parlib" alarm handlers */
void alarm_abort_sysc(struct alarm_waiter *awaiter);
/* Debugging */
#define ALARM_POISON_TIME 12345
void print_chain(struct timer_chain *tchain);
#endif /* _ALARM_H */