diff options
Diffstat (limited to 'include/linux/hrtimer.h')
-rw-r--r-- | include/linux/hrtimer.h | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 012c37fdb688..c7902ca7c9f4 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -28,13 +28,29 @@ struct hrtimer_cpu_base; | |||
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Mode arguments of xxx_hrtimer functions: | 30 | * Mode arguments of xxx_hrtimer functions: |
31 | * | ||
32 | * HRTIMER_MODE_ABS - Time value is absolute | ||
33 | * HRTIMER_MODE_REL - Time value is relative to now | ||
34 | * HRTIMER_MODE_PINNED - Timer is bound to CPU (is only considered | ||
35 | * when starting the timer) | ||
36 | * HRTIMER_MODE_SOFT - Timer callback function will be executed in | ||
37 | * soft irq context | ||
31 | */ | 38 | */ |
32 | enum hrtimer_mode { | 39 | enum hrtimer_mode { |
33 | HRTIMER_MODE_ABS = 0x0, /* Time value is absolute */ | 40 | HRTIMER_MODE_ABS = 0x00, |
34 | HRTIMER_MODE_REL = 0x1, /* Time value is relative to now */ | 41 | HRTIMER_MODE_REL = 0x01, |
35 | HRTIMER_MODE_PINNED = 0x02, /* Timer is bound to CPU */ | 42 | HRTIMER_MODE_PINNED = 0x02, |
36 | HRTIMER_MODE_ABS_PINNED = 0x02, | 43 | HRTIMER_MODE_SOFT = 0x04, |
37 | HRTIMER_MODE_REL_PINNED = 0x03, | 44 | |
45 | HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED, | ||
46 | HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED, | ||
47 | |||
48 | HRTIMER_MODE_ABS_SOFT = HRTIMER_MODE_ABS | HRTIMER_MODE_SOFT, | ||
49 | HRTIMER_MODE_REL_SOFT = HRTIMER_MODE_REL | HRTIMER_MODE_SOFT, | ||
50 | |||
51 | HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT, | ||
52 | HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT, | ||
53 | |||
38 | }; | 54 | }; |
39 | 55 | ||
40 | /* | 56 | /* |
@@ -87,6 +103,7 @@ enum hrtimer_restart { | |||
87 | * @base: pointer to the timer base (per cpu and per clock) | 103 | * @base: pointer to the timer base (per cpu and per clock) |
88 | * @state: state information (See bit values above) | 104 | * @state: state information (See bit values above) |
89 | * @is_rel: Set if the timer was armed relative | 105 | * @is_rel: Set if the timer was armed relative |
106 | * @is_soft: Set if hrtimer will be expired in soft interrupt context. | ||
90 | * | 107 | * |
91 | * The hrtimer structure must be initialized by hrtimer_init() | 108 | * The hrtimer structure must be initialized by hrtimer_init() |
92 | */ | 109 | */ |
@@ -97,6 +114,7 @@ struct hrtimer { | |||
97 | struct hrtimer_clock_base *base; | 114 | struct hrtimer_clock_base *base; |
98 | u8 state; | 115 | u8 state; |
99 | u8 is_rel; | 116 | u8 is_rel; |
117 | u8 is_soft; | ||
100 | }; | 118 | }; |
101 | 119 | ||
102 | /** | 120 | /** |
@@ -112,9 +130,9 @@ struct hrtimer_sleeper { | |||
112 | }; | 130 | }; |
113 | 131 | ||
114 | #ifdef CONFIG_64BIT | 132 | #ifdef CONFIG_64BIT |
115 | # define HRTIMER_CLOCK_BASE_ALIGN 64 | 133 | # define __hrtimer_clock_base_align ____cacheline_aligned |
116 | #else | 134 | #else |
117 | # define HRTIMER_CLOCK_BASE_ALIGN 32 | 135 | # define __hrtimer_clock_base_align |
118 | #endif | 136 | #endif |
119 | 137 | ||
120 | /** | 138 | /** |
@@ -123,48 +141,57 @@ struct hrtimer_sleeper { | |||
123 | * @index: clock type index for per_cpu support when moving a | 141 | * @index: clock type index for per_cpu support when moving a |
124 | * timer to a base on another cpu. | 142 | * timer to a base on another cpu. |
125 | * @clockid: clock id for per_cpu support | 143 | * @clockid: clock id for per_cpu support |
144 | * @seq: seqcount around __run_hrtimer | ||
145 | * @running: pointer to the currently running hrtimer | ||
126 | * @active: red black tree root node for the active timers | 146 | * @active: red black tree root node for the active timers |
127 | * @get_time: function to retrieve the current time of the clock | 147 | * @get_time: function to retrieve the current time of the clock |
128 | * @offset: offset of this clock to the monotonic base | 148 | * @offset: offset of this clock to the monotonic base |
129 | */ | 149 | */ |
130 | struct hrtimer_clock_base { | 150 | struct hrtimer_clock_base { |
131 | struct hrtimer_cpu_base *cpu_base; | 151 | struct hrtimer_cpu_base *cpu_base; |
132 | int index; | 152 | unsigned int index; |
133 | clockid_t clockid; | 153 | clockid_t clockid; |
154 | seqcount_t seq; | ||
155 | struct hrtimer *running; | ||
134 | struct timerqueue_head active; | 156 | struct timerqueue_head active; |
135 | ktime_t (*get_time)(void); | 157 | ktime_t (*get_time)(void); |
136 | ktime_t offset; | 158 | ktime_t offset; |
137 | } __attribute__((__aligned__(HRTIMER_CLOCK_BASE_ALIGN))); | 159 | } __hrtimer_clock_base_align; |
138 | 160 | ||
139 | enum hrtimer_base_type { | 161 | enum hrtimer_base_type { |
140 | HRTIMER_BASE_MONOTONIC, | 162 | HRTIMER_BASE_MONOTONIC, |
141 | HRTIMER_BASE_REALTIME, | 163 | HRTIMER_BASE_REALTIME, |
142 | HRTIMER_BASE_BOOTTIME, | 164 | HRTIMER_BASE_BOOTTIME, |
143 | HRTIMER_BASE_TAI, | 165 | HRTIMER_BASE_TAI, |
166 | HRTIMER_BASE_MONOTONIC_SOFT, | ||
167 | HRTIMER_BASE_REALTIME_SOFT, | ||
168 | HRTIMER_BASE_BOOTTIME_SOFT, | ||
169 | HRTIMER_BASE_TAI_SOFT, | ||
144 | HRTIMER_MAX_CLOCK_BASES, | 170 | HRTIMER_MAX_CLOCK_BASES, |
145 | }; | 171 | }; |
146 | 172 | ||
147 | /* | 173 | /** |
148 | * struct hrtimer_cpu_base - the per cpu clock bases | 174 | * struct hrtimer_cpu_base - the per cpu clock bases |
149 | * @lock: lock protecting the base and associated clock bases | 175 | * @lock: lock protecting the base and associated clock bases |
150 | * and timers | 176 | * and timers |
151 | * @seq: seqcount around __run_hrtimer | ||
152 | * @running: pointer to the currently running hrtimer | ||
153 | * @cpu: cpu number | 177 | * @cpu: cpu number |
154 | * @active_bases: Bitfield to mark bases with active timers | 178 | * @active_bases: Bitfield to mark bases with active timers |
155 | * @clock_was_set_seq: Sequence counter of clock was set events | 179 | * @clock_was_set_seq: Sequence counter of clock was set events |
156 | * @migration_enabled: The migration of hrtimers to other cpus is enabled | ||
157 | * @nohz_active: The nohz functionality is enabled | ||
158 | * @expires_next: absolute time of the next event which was scheduled | ||
159 | * via clock_set_next_event() | ||
160 | * @next_timer: Pointer to the first expiring timer | ||
161 | * @in_hrtirq: hrtimer_interrupt() is currently executing | ||
162 | * @hres_active: State of high resolution mode | 180 | * @hres_active: State of high resolution mode |
181 | * @in_hrtirq: hrtimer_interrupt() is currently executing | ||
163 | * @hang_detected: The last hrtimer interrupt detected a hang | 182 | * @hang_detected: The last hrtimer interrupt detected a hang |
183 | * @softirq_activated: displays, if the softirq is raised - update of softirq | ||
184 | * related settings is not required then. | ||
164 | * @nr_events: Total number of hrtimer interrupt events | 185 | * @nr_events: Total number of hrtimer interrupt events |
165 | * @nr_retries: Total number of hrtimer interrupt retries | 186 | * @nr_retries: Total number of hrtimer interrupt retries |
166 | * @nr_hangs: Total number of hrtimer interrupt hangs | 187 | * @nr_hangs: Total number of hrtimer interrupt hangs |
167 | * @max_hang_time: Maximum time spent in hrtimer_interrupt | 188 | * @max_hang_time: Maximum time spent in hrtimer_interrupt |
189 | * @expires_next: absolute time of the next event, is required for remote | ||
190 | * hrtimer enqueue; it is the total first expiry time (hard | ||
191 | * and soft hrtimer are taken into account) | ||
192 | * @next_timer: Pointer to the first expiring timer | ||
193 | * @softirq_expires_next: Time to check, if soft queues needs also to be expired | ||
194 | * @softirq_next_timer: Pointer to the first expiring softirq based timer | ||
168 | * @clock_base: array of clock bases for this cpu | 195 | * @clock_base: array of clock bases for this cpu |
169 | * | 196 | * |
170 | * Note: next_timer is just an optimization for __remove_hrtimer(). | 197 | * Note: next_timer is just an optimization for __remove_hrtimer(). |
@@ -173,31 +200,28 @@ enum hrtimer_base_type { | |||
173 | */ | 200 | */ |
174 | struct hrtimer_cpu_base { | 201 | struct hrtimer_cpu_base { |
175 | raw_spinlock_t lock; | 202 | raw_spinlock_t lock; |
176 | seqcount_t seq; | ||
177 | struct hrtimer *running; | ||
178 | unsigned int cpu; | 203 | unsigned int cpu; |
179 | unsigned int active_bases; | 204 | unsigned int active_bases; |
180 | unsigned int clock_was_set_seq; | 205 | unsigned int clock_was_set_seq; |
181 | bool migration_enabled; | 206 | unsigned int hres_active : 1, |
182 | bool nohz_active; | 207 | in_hrtirq : 1, |
208 | hang_detected : 1, | ||
209 | softirq_activated : 1; | ||
183 | #ifdef CONFIG_HIGH_RES_TIMERS | 210 | #ifdef CONFIG_HIGH_RES_TIMERS |
184 | unsigned int in_hrtirq : 1, | ||
185 | hres_active : 1, | ||
186 | hang_detected : 1; | ||
187 | ktime_t expires_next; | ||
188 | struct hrtimer *next_timer; | ||
189 | unsigned int nr_events; | 211 | unsigned int nr_events; |
190 | unsigned int nr_retries; | 212 | unsigned short nr_retries; |
191 | unsigned int nr_hangs; | 213 | unsigned short nr_hangs; |
192 | unsigned int max_hang_time; | 214 | unsigned int max_hang_time; |
193 | #endif | 215 | #endif |
216 | ktime_t expires_next; | ||
217 | struct hrtimer *next_timer; | ||
218 | ktime_t softirq_expires_next; | ||
219 | struct hrtimer *softirq_next_timer; | ||
194 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; | 220 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; |
195 | } ____cacheline_aligned; | 221 | } ____cacheline_aligned; |
196 | 222 | ||
197 | static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time) | 223 | static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time) |
198 | { | 224 | { |
199 | BUILD_BUG_ON(sizeof(struct hrtimer_clock_base) > HRTIMER_CLOCK_BASE_ALIGN); | ||
200 | |||
201 | timer->node.expires = time; | 225 | timer->node.expires = time; |
202 | timer->_softexpires = time; | 226 | timer->_softexpires = time; |
203 | } | 227 | } |
@@ -266,16 +290,17 @@ static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer) | |||
266 | return timer->base->get_time(); | 290 | return timer->base->get_time(); |
267 | } | 291 | } |
268 | 292 | ||
293 | static inline int hrtimer_is_hres_active(struct hrtimer *timer) | ||
294 | { | ||
295 | return IS_ENABLED(CONFIG_HIGH_RES_TIMERS) ? | ||
296 | timer->base->cpu_base->hres_active : 0; | ||
297 | } | ||
298 | |||
269 | #ifdef CONFIG_HIGH_RES_TIMERS | 299 | #ifdef CONFIG_HIGH_RES_TIMERS |
270 | struct clock_event_device; | 300 | struct clock_event_device; |
271 | 301 | ||
272 | extern void hrtimer_interrupt(struct clock_event_device *dev); | 302 | extern void hrtimer_interrupt(struct clock_event_device *dev); |
273 | 303 | ||
274 | static inline int hrtimer_is_hres_active(struct hrtimer *timer) | ||
275 | { | ||
276 | return timer->base->cpu_base->hres_active; | ||
277 | } | ||
278 | |||
279 | /* | 304 | /* |
280 | * The resolution of the clocks. The resolution value is returned in | 305 | * The resolution of the clocks. The resolution value is returned in |
281 | * the clock_getres() system call to give application programmers an | 306 | * the clock_getres() system call to give application programmers an |
@@ -298,11 +323,6 @@ extern unsigned int hrtimer_resolution; | |||
298 | 323 | ||
299 | #define hrtimer_resolution (unsigned int)LOW_RES_NSEC | 324 | #define hrtimer_resolution (unsigned int)LOW_RES_NSEC |
300 | 325 | ||
301 | static inline int hrtimer_is_hres_active(struct hrtimer *timer) | ||
302 | { | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static inline void clock_was_set_delayed(void) { } | 326 | static inline void clock_was_set_delayed(void) { } |
307 | 327 | ||
308 | #endif | 328 | #endif |
@@ -365,11 +385,12 @@ extern void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, | |||
365 | u64 range_ns, const enum hrtimer_mode mode); | 385 | u64 range_ns, const enum hrtimer_mode mode); |
366 | 386 | ||
367 | /** | 387 | /** |
368 | * hrtimer_start - (re)start an hrtimer on the current CPU | 388 | * hrtimer_start - (re)start an hrtimer |
369 | * @timer: the timer to be added | 389 | * @timer: the timer to be added |
370 | * @tim: expiry time | 390 | * @tim: expiry time |
371 | * @mode: expiry mode: absolute (HRTIMER_MODE_ABS) or | 391 | * @mode: timer mode: absolute (HRTIMER_MODE_ABS) or |
372 | * relative (HRTIMER_MODE_REL) | 392 | * relative (HRTIMER_MODE_REL), and pinned (HRTIMER_MODE_PINNED); |
393 | * softirq based mode is considered for debug purpose only! | ||
373 | */ | 394 | */ |
374 | static inline void hrtimer_start(struct hrtimer *timer, ktime_t tim, | 395 | static inline void hrtimer_start(struct hrtimer *timer, ktime_t tim, |
375 | const enum hrtimer_mode mode) | 396 | const enum hrtimer_mode mode) |
@@ -422,7 +443,7 @@ static inline int hrtimer_is_queued(struct hrtimer *timer) | |||
422 | */ | 443 | */ |
423 | static inline int hrtimer_callback_running(struct hrtimer *timer) | 444 | static inline int hrtimer_callback_running(struct hrtimer *timer) |
424 | { | 445 | { |
425 | return timer->base->cpu_base->running == timer; | 446 | return timer->base->running == timer; |
426 | } | 447 | } |
427 | 448 | ||
428 | /* Forward a hrtimer so it expires after now: */ | 449 | /* Forward a hrtimer so it expires after now: */ |
@@ -466,7 +487,7 @@ extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta, | |||
466 | extern int schedule_hrtimeout_range_clock(ktime_t *expires, | 487 | extern int schedule_hrtimeout_range_clock(ktime_t *expires, |
467 | u64 delta, | 488 | u64 delta, |
468 | const enum hrtimer_mode mode, | 489 | const enum hrtimer_mode mode, |
469 | int clock); | 490 | clockid_t clock_id); |
470 | extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode); | 491 | extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode); |
471 | 492 | ||
472 | /* Soft interrupt function to run the hrtimer queues: */ | 493 | /* Soft interrupt function to run the hrtimer queues: */ |