diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-02-16 04:27:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-16 11:13:58 -0500 |
commit | 303e967ff90a9d19ad3f8c9028ccbfa7f408fbb3 (patch) | |
tree | cd8c057e98b57896ffbbe4d98a4264393a652204 /include/linux/hrtimer.h | |
parent | 3c8aa39d7c445ae2612b6b626f76f077e7a7ab0d (diff) |
[PATCH] hrtimers; add state tracking
Reintroduce ktimers feature "optimized away" by the ktimers review process:
multiple hrtimer states to enable the running of hrtimers without holding the
cpu-base-lock.
(The "optimized" rbtree hack carried only 2 states worth of information and we
need 4 for high resolution timers and dynamic ticks.)
No functional changes.
Build-fixes-from: Andrew Morton <akpm@osdl.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/hrtimer.h')
-rw-r--r-- | include/linux/hrtimer.h | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index e00fc4d3d74f..d8cdac2d28d6 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -40,6 +40,34 @@ enum hrtimer_restart { | |||
40 | HRTIMER_RESTART, /* Timer must be restarted */ | 40 | HRTIMER_RESTART, /* Timer must be restarted */ |
41 | }; | 41 | }; |
42 | 42 | ||
43 | /* | ||
44 | * Bit values to track state of the timer | ||
45 | * | ||
46 | * Possible states: | ||
47 | * | ||
48 | * 0x00 inactive | ||
49 | * 0x01 enqueued into rbtree | ||
50 | * 0x02 callback function running | ||
51 | * 0x03 callback function running and enqueued | ||
52 | * (was requeued on another CPU) | ||
53 | * | ||
54 | * 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 | ||
56 | * queued a signal. Between dropping the lock which protects the posix timer | ||
57 | * and reacquiring the base lock of the hrtimer, another CPU can deliver the | ||
58 | * signal and rearm the timer. We have to preserve the callback running state, | ||
59 | * as otherwise the timer could be removed before the softirq code finishes the | ||
60 | * the handling of the timer. | ||
61 | * | ||
62 | * The HRTIMER_STATE_ENQUEUE bit is always or'ed to the current state to | ||
63 | * preserve the HRTIMER_STATE_CALLBACK bit in the above scenario. | ||
64 | * | ||
65 | * All state transitions are protected by cpu_base->lock. | ||
66 | */ | ||
67 | #define HRTIMER_STATE_INACTIVE 0x00 | ||
68 | #define HRTIMER_STATE_ENQUEUED 0x01 | ||
69 | #define HRTIMER_STATE_CALLBACK 0x02 | ||
70 | |||
43 | /** | 71 | /** |
44 | * struct hrtimer - the basic hrtimer structure | 72 | * struct hrtimer - the basic hrtimer structure |
45 | * @node: red black tree node for time ordered insertion | 73 | * @node: red black tree node for time ordered insertion |
@@ -48,6 +76,7 @@ enum hrtimer_restart { | |||
48 | * which the timer is based. | 76 | * which the timer is based. |
49 | * @function: timer expiry callback function | 77 | * @function: timer expiry callback function |
50 | * @base: pointer to the timer base (per cpu and per clock) | 78 | * @base: pointer to the timer base (per cpu and per clock) |
79 | * @state: state information (See bit values above) | ||
51 | * | 80 | * |
52 | * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE() | 81 | * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE() |
53 | */ | 82 | */ |
@@ -56,6 +85,7 @@ struct hrtimer { | |||
56 | ktime_t expires; | 85 | ktime_t expires; |
57 | enum hrtimer_restart (*function)(struct hrtimer *); | 86 | enum hrtimer_restart (*function)(struct hrtimer *); |
58 | struct hrtimer_clock_base *base; | 87 | struct hrtimer_clock_base *base; |
88 | unsigned long state; | ||
59 | }; | 89 | }; |
60 | 90 | ||
61 | /** | 91 | /** |
@@ -141,9 +171,13 @@ extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp); | |||
141 | extern ktime_t hrtimer_get_next_event(void); | 171 | extern ktime_t hrtimer_get_next_event(void); |
142 | #endif | 172 | #endif |
143 | 173 | ||
174 | /* | ||
175 | * A timer is active, when it is enqueued into the rbtree or the callback | ||
176 | * function is running. | ||
177 | */ | ||
144 | static inline int hrtimer_active(const struct hrtimer *timer) | 178 | static inline int hrtimer_active(const struct hrtimer *timer) |
145 | { | 179 | { |
146 | return rb_parent(&timer->node) != &timer->node; | 180 | return timer->state != HRTIMER_STATE_INACTIVE; |
147 | } | 181 | } |
148 | 182 | ||
149 | /* Forward a hrtimer so it expires after now: */ | 183 | /* Forward a hrtimer so it expires after now: */ |