aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-02-16 04:28:11 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:13:59 -0500
commit54cdfdb47f73b5af3d1ebb0f1e383efbe70fde9e (patch)
treee2f76277f6b7546e53c3a1d025e31bceb10bbff5 /include
parentd40891e75fc1f646dce57d5d3bd1349a6aaf7a0e (diff)
[PATCH] hrtimers: add high resolution timer support
Implement high resolution timers on top of the hrtimers infrastructure and the clockevents / tick-management framework. This provides accurate timers for all hrtimer subsystem users. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/hrtimer.h116
-rw-r--r--include/linux/interrupt.h3
-rw-r--r--include/linux/ktime.h3
3 files changed, 114 insertions, 8 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index e95c96c971c0..4ecd991431b4 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -41,16 +41,35 @@ enum hrtimer_restart {
41}; 41};
42 42
43/* 43/*
44 * Bit values to track state of the timer 44 * hrtimer callback modes:
45 *
46 * HRTIMER_CB_SOFTIRQ: Callback must run in softirq context
47 * HRTIMER_CB_IRQSAFE: Callback may run in hardirq context
48 * HRTIMER_CB_IRQSAFE_NO_RESTART: Callback may run in hardirq context and
49 * does not restart the timer
50 * HRTIMER_CB_IRQSAFE_NO_SOFTIRQ: Callback must run in softirq context
51 * Special mode for tick emultation
52 */
53enum hrtimer_cb_mode {
54 HRTIMER_CB_SOFTIRQ,
55 HRTIMER_CB_IRQSAFE,
56 HRTIMER_CB_IRQSAFE_NO_RESTART,
57 HRTIMER_CB_IRQSAFE_NO_SOFTIRQ,
58};
59
60/*
61 * Values to track state of the timer
45 * 62 *
46 * Possible states: 63 * Possible states:
47 * 64 *
48 * 0x00 inactive 65 * 0x00 inactive
49 * 0x01 enqueued into rbtree 66 * 0x01 enqueued into rbtree
50 * 0x02 callback function running 67 * 0x02 callback function running
68 * 0x04 callback pending (high resolution mode)
69 *
70 * Special case:
51 * 0x03 callback function running and enqueued 71 * 0x03 callback function running and enqueued
52 * (was requeued on another CPU) 72 * (was requeued on another CPU)
53 *
54 * The "callback function running and enqueued" status is only possible on 73 * The "callback function running and enqueued" status is only possible on
55 * SMP. It happens for example when a posix timer expired and the callback 74 * SMP. It happens for example when a posix timer expired and the callback
56 * queued a signal. Between dropping the lock which protects the posix timer 75 * queued a signal. Between dropping the lock which protects the posix timer
@@ -67,6 +86,7 @@ enum hrtimer_restart {
67#define HRTIMER_STATE_INACTIVE 0x00 86#define HRTIMER_STATE_INACTIVE 0x00
68#define HRTIMER_STATE_ENQUEUED 0x01 87#define HRTIMER_STATE_ENQUEUED 0x01
69#define HRTIMER_STATE_CALLBACK 0x02 88#define HRTIMER_STATE_CALLBACK 0x02
89#define HRTIMER_STATE_PENDING 0x04
70 90
71/** 91/**
72 * struct hrtimer - the basic hrtimer structure 92 * struct hrtimer - the basic hrtimer structure
@@ -77,8 +97,17 @@ enum hrtimer_restart {
77 * @function: timer expiry callback function 97 * @function: timer expiry callback function
78 * @base: pointer to the timer base (per cpu and per clock) 98 * @base: pointer to the timer base (per cpu and per clock)
79 * @state: state information (See bit values above) 99 * @state: state information (See bit values above)
100 * @cb_mode: high resolution timer feature to select the callback execution
101 * mode
102 * @cb_entry: list head to enqueue an expired timer into the callback list
103 * @start_site: timer statistics field to store the site where the timer
104 * was started
105 * @start_comm: timer statistics field to store the name of the process which
106 * started the timer
107 * @start_pid: timer statistics field to store the pid of the task which
108 * started the timer
80 * 109 *
81 * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE() 110 * The hrtimer structure must be initialized by hrtimer_init()
82 */ 111 */
83struct hrtimer { 112struct hrtimer {
84 struct rb_node node; 113 struct rb_node node;
@@ -86,6 +115,10 @@ struct hrtimer {
86 enum hrtimer_restart (*function)(struct hrtimer *); 115 enum hrtimer_restart (*function)(struct hrtimer *);
87 struct hrtimer_clock_base *base; 116 struct hrtimer_clock_base *base;
88 unsigned long state; 117 unsigned long state;
118#ifdef CONFIG_HIGH_RES_TIMERS
119 enum hrtimer_cb_mode cb_mode;
120 struct list_head cb_entry;
121#endif
89}; 122};
90 123
91/** 124/**
@@ -110,6 +143,9 @@ struct hrtimer_sleeper {
110 * @get_time: function to retrieve the current time of the clock 143 * @get_time: function to retrieve the current time of the clock
111 * @get_softirq_time: function to retrieve the current time from the softirq 144 * @get_softirq_time: function to retrieve the current time from the softirq
112 * @softirq_time: the time when running the hrtimer queue in the softirq 145 * @softirq_time: the time when running the hrtimer queue in the softirq
146 * @cb_pending: list of timers where the callback is pending
147 * @offset: offset of this clock to the monotonic base
148 * @reprogram: function to reprogram the timer event
113 */ 149 */
114struct hrtimer_clock_base { 150struct hrtimer_clock_base {
115 struct hrtimer_cpu_base *cpu_base; 151 struct hrtimer_cpu_base *cpu_base;
@@ -120,6 +156,12 @@ struct hrtimer_clock_base {
120 ktime_t (*get_time)(void); 156 ktime_t (*get_time)(void);
121 ktime_t (*get_softirq_time)(void); 157 ktime_t (*get_softirq_time)(void);
122 ktime_t softirq_time; 158 ktime_t softirq_time;
159#ifdef CONFIG_HIGH_RES_TIMERS
160 ktime_t offset;
161 int (*reprogram)(struct hrtimer *t,
162 struct hrtimer_clock_base *b,
163 ktime_t n);
164#endif
123}; 165};
124 166
125#define HRTIMER_MAX_CLOCK_BASES 2 167#define HRTIMER_MAX_CLOCK_BASES 2
@@ -131,19 +173,74 @@ struct hrtimer_clock_base {
131 * @lock_key: the lock_class_key for use with lockdep 173 * @lock_key: the lock_class_key for use with lockdep
132 * @clock_base: array of clock bases for this cpu 174 * @clock_base: array of clock bases for this cpu
133 * @curr_timer: the timer which is executing a callback right now 175 * @curr_timer: the timer which is executing a callback right now
176 * @expires_next: absolute time of the next event which was scheduled
177 * via clock_set_next_event()
178 * @hres_active: State of high resolution mode
179 * @check_clocks: Indictator, when set evaluate time source and clock
180 * event devices whether high resolution mode can be
181 * activated.
182 * @cb_pending: Expired timers are moved from the rbtree to this
183 * list in the timer interrupt. The list is processed
184 * in the softirq.
185 * @nr_events: Total number of timer interrupt events
134 */ 186 */
135struct hrtimer_cpu_base { 187struct hrtimer_cpu_base {
136 spinlock_t lock; 188 spinlock_t lock;
137 struct lock_class_key lock_key; 189 struct lock_class_key lock_key;
138 struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; 190 struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
191#ifdef CONFIG_HIGH_RES_TIMERS
192 ktime_t expires_next;
193 int hres_active;
194 struct list_head cb_pending;
195 unsigned long nr_events;
196#endif
139}; 197};
140 198
199#ifdef CONFIG_HIGH_RES_TIMERS
200struct clock_event_device;
201
202extern void clock_was_set(void);
203extern void hrtimer_interrupt(struct clock_event_device *dev);
204
205/*
206 * In high resolution mode the time reference must be read accurate
207 */
208static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
209{
210 return timer->base->get_time();
211}
212
213/*
214 * The resolution of the clocks. The resolution value is returned in
215 * the clock_getres() system call to give application programmers an
216 * idea of the (in)accuracy of timers. Timer values are rounded up to
217 * this resolution values.
218 */
219# define KTIME_HIGH_RES (ktime_t) { .tv64 = 1 }
220# define KTIME_MONOTONIC_RES KTIME_HIGH_RES
221
222#else
223
224# define KTIME_MONOTONIC_RES KTIME_LOW_RES
225
141/* 226/*
142 * clock_was_set() is a NOP for non- high-resolution systems. The 227 * clock_was_set() is a NOP for non- high-resolution systems. The
143 * time-sorted order guarantees that a timer does not expire early and 228 * time-sorted order guarantees that a timer does not expire early and
144 * is expired in the next softirq when the clock was advanced. 229 * is expired in the next softirq when the clock was advanced.
145 */ 230 */
146#define clock_was_set() do { } while (0) 231static inline void clock_was_set(void) { }
232
233/*
234 * In non high resolution mode the time reference is taken from
235 * the base softirq time variable.
236 */
237static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
238{
239 return timer->base->softirq_time;
240}
241
242#endif
243
147extern ktime_t ktime_get(void); 244extern ktime_t ktime_get(void);
148extern ktime_t ktime_get_real(void); 245extern ktime_t ktime_get_real(void);
149 246
@@ -168,9 +265,7 @@ static inline int hrtimer_restart(struct hrtimer *timer)
168extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer); 265extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
169extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp); 266extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
170 267
171#ifdef CONFIG_NO_IDLE_HZ
172extern ktime_t hrtimer_get_next_event(void); 268extern ktime_t hrtimer_get_next_event(void);
173#endif
174 269
175/* 270/*
176 * A timer is active, when it is enqueued into the rbtree or the callback 271 * A timer is active, when it is enqueued into the rbtree or the callback
@@ -181,6 +276,15 @@ static inline int hrtimer_active(const struct hrtimer *timer)
181 return timer->state != HRTIMER_STATE_INACTIVE; 276 return timer->state != HRTIMER_STATE_INACTIVE;
182} 277}
183 278
279/*
280 * Helper function to check, whether the timer is on one of the queues
281 */
282static inline int hrtimer_is_queued(struct hrtimer *timer)
283{
284 return timer->state &
285 (HRTIMER_STATE_ENQUEUED | HRTIMER_STATE_PENDING);
286}
287
184/* Forward a hrtimer so it expires after now: */ 288/* Forward a hrtimer so it expires after now: */
185extern unsigned long 289extern unsigned long
186hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval); 290hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 690113d07698..e5ea1411050b 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -242,6 +242,9 @@ enum
242 BLOCK_SOFTIRQ, 242 BLOCK_SOFTIRQ,
243 TASKLET_SOFTIRQ, 243 TASKLET_SOFTIRQ,
244 SCHED_SOFTIRQ, 244 SCHED_SOFTIRQ,
245#ifdef CONFIG_HIGH_RES_TIMERS
246 HRTIMER_SOFTIRQ,
247#endif
245}; 248};
246 249
247/* softirq mask and active fields moved to irq_cpustat_t in 250/* softirq mask and active fields moved to irq_cpustat_t in
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 7444a6326231..c68c7ac6b232 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -261,8 +261,7 @@ static inline s64 ktime_to_ns(const ktime_t kt)
261 * idea of the (in)accuracy of timers. Timer values are rounded up to 261 * idea of the (in)accuracy of timers. Timer values are rounded up to
262 * this resolution values. 262 * this resolution values.
263 */ 263 */
264#define KTIME_REALTIME_RES (ktime_t){ .tv64 = TICK_NSEC } 264#define KTIME_LOW_RES (ktime_t){ .tv64 = TICK_NSEC }
265#define KTIME_MONOTONIC_RES (ktime_t){ .tv64 = TICK_NSEC }
266 265
267/* Get the monotonic time in timespec format: */ 266/* Get the monotonic time in timespec format: */
268extern void ktime_get_ts(struct timespec *ts); 267extern void ktime_get_ts(struct timespec *ts);