#include <linux/list.h>
#include <linux/wait.h>
+struct hrtimer_clock_base;
+struct hrtimer_cpu_base;
+
/*
* Mode arguments of xxx_hrtimer functions:
*/
enum hrtimer_mode {
- HRTIMER_ABS, /* Time value is absolute */
- HRTIMER_REL, /* Time value is relative to now */
+ HRTIMER_MODE_ABS, /* Time value is absolute */
+ HRTIMER_MODE_REL, /* Time value is relative to now */
};
+/*
+ * Return values for the callback function
+ */
enum hrtimer_restart {
- HRTIMER_NORESTART,
- HRTIMER_RESTART,
+ HRTIMER_NORESTART, /* Timer is not restarted */
+ HRTIMER_RESTART, /* Timer must be restarted */
};
-#define HRTIMER_INACTIVE ((void *)1UL)
-
-struct hrtimer_base;
+/*
+ * Bit values to track state of the timer
+ *
+ * Possible states:
+ *
+ * 0x00 inactive
+ * 0x01 enqueued into rbtree
+ * 0x02 callback function running
+ * 0x03 callback function running and enqueued
+ * (was requeued on another CPU)
+ *
+ * The "callback function running and enqueued" status is only possible on
+ * SMP. It happens for example when a posix timer expired and the callback
+ * queued a signal. Between dropping the lock which protects the posix timer
+ * and reacquiring the base lock of the hrtimer, another CPU can deliver the
+ * signal and rearm the timer. We have to preserve the callback running state,
+ * as otherwise the timer could be removed before the softirq code finishes the
+ * the handling of the timer.
+ *
+ * The HRTIMER_STATE_ENQUEUE bit is always or'ed to the current state to
+ * preserve the HRTIMER_STATE_CALLBACK bit in the above scenario.
+ *
+ * All state transitions are protected by cpu_base->lock.
+ */
+#define HRTIMER_STATE_INACTIVE 0x00
+#define HRTIMER_STATE_ENQUEUED 0x01
+#define HRTIMER_STATE_CALLBACK 0x02
/**
* struct hrtimer - the basic hrtimer structure
* which the timer is based.
* @function: timer expiry callback function
* @base: pointer to the timer base (per cpu and per clock)
+ * @state: state information (See bit values above)
*
* The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
*/
struct hrtimer {
- struct rb_node node;
- ktime_t expires;
- int (*function)(struct hrtimer *);
- struct hrtimer_base *base;
+ struct rb_node node;
+ ktime_t expires;
+ enum hrtimer_restart (*function)(struct hrtimer *);
+ struct hrtimer_clock_base *base;
+ unsigned long state;
};
/**
/**
* struct hrtimer_base - the timer base for a specific clock
- * @index: clock type index for per_cpu support when moving a timer
- * to a base on another cpu.
- * @lock: lock protecting the base and associated timers
+ * @index: clock type index for per_cpu support when moving a
+ * timer to a base on another cpu.
* @active: red black tree root node for the active timers
* @first: pointer to the timer node which expires first
* @resolution: the resolution of the clock, in nanoseconds
* @get_time: function to retrieve the current time of the clock
* @get_softirq_time: function to retrieve the current time from the softirq
- * @curr_timer: the timer which is executing a callback right now
* @softirq_time: the time when running the hrtimer queue in the softirq
*/
-struct hrtimer_base {
+struct hrtimer_clock_base {
+ struct hrtimer_cpu_base *cpu_base;
clockid_t index;
- spinlock_t lock;
struct rb_root active;
struct rb_node *first;
ktime_t resolution;
ktime_t (*get_time)(void);
ktime_t (*get_softirq_time)(void);
- struct hrtimer *curr_timer;
ktime_t softirq_time;
};
+#define HRTIMER_MAX_CLOCK_BASES 2
+
+/*
+ * struct hrtimer_cpu_base - the per cpu clock bases
+ * @lock: lock protecting the base and associated clock bases
+ * and timers
+ * @lock_key: the lock_class_key for use with lockdep
+ * @clock_base: array of clock bases for this cpu
+ * @curr_timer: the timer which is executing a callback right now
+ */
+struct hrtimer_cpu_base {
+ spinlock_t lock;
+ struct lock_class_key lock_key;
+ struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
+};
+
/*
* clock_was_set() is a NOP for non- high-resolution systems. The
* time-sorted order guarantees that a timer does not expire early and
* is expired in the next softirq when the clock was advanced.
*/
#define clock_was_set() do { } while (0)
+extern ktime_t ktime_get(void);
+extern ktime_t ktime_get_real(void);
/* Exported timer functions: */
extern int hrtimer_cancel(struct hrtimer *timer);
extern int hrtimer_try_to_cancel(struct hrtimer *timer);
-#define hrtimer_restart(timer) hrtimer_start((timer), (timer)->expires, HRTIMER_ABS)
+static inline int hrtimer_restart(struct hrtimer *timer)
+{
+ return hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS);
+}
/* Query timers: */
extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
extern ktime_t hrtimer_get_next_event(void);
#endif
+/*
+ * A timer is active, when it is enqueued into the rbtree or the callback
+ * function is running.
+ */
static inline int hrtimer_active(const struct hrtimer *timer)
{
- return rb_parent(&timer->node) != &timer->node;
+ return timer->state != HRTIMER_STATE_INACTIVE;
}
/* Forward a hrtimer so it expires after now: */
struct timespec __user *rmtp,
const enum hrtimer_mode mode,
const clockid_t clockid);
+extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
struct task_struct *tsk);
/* Bootup initialization: */
extern void __init hrtimers_init(void);
+#if BITS_PER_LONG < 64
+extern unsigned long ktime_divns(const ktime_t kt, s64 div);
+#else /* BITS_PER_LONG < 64 */
+# define ktime_divns(kt, div) (unsigned long)((kt).tv64 / (div))
+#endif
+
#endif