| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | | - * include/linux/hrtimer.h |
|---|
| 3 | | - * |
|---|
| 4 | 3 | * hrtimers - High-resolution kernel timers |
|---|
| 5 | 4 | * |
|---|
| 6 | 5 | * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de> |
|---|
| .. | .. |
|---|
| 9 | 8 | * data type definitions, declarations, prototypes |
|---|
| 10 | 9 | * |
|---|
| 11 | 10 | * Started by: Thomas Gleixner and Ingo Molnar |
|---|
| 12 | | - * |
|---|
| 13 | | - * For licencing details see kernel-base/COPYING |
|---|
| 14 | 11 | */ |
|---|
| 15 | 12 | #ifndef _LINUX_HRTIMER_H |
|---|
| 16 | 13 | #define _LINUX_HRTIMER_H |
|---|
| .. | .. |
|---|
| 20 | 17 | #include <linux/init.h> |
|---|
| 21 | 18 | #include <linux/list.h> |
|---|
| 22 | 19 | #include <linux/percpu.h> |
|---|
| 20 | +#include <linux/seqlock.h> |
|---|
| 23 | 21 | #include <linux/timer.h> |
|---|
| 24 | 22 | #include <linux/timerqueue.h> |
|---|
| 25 | 23 | #include <linux/android_kabi.h> |
|---|
| .. | .. |
|---|
| 36 | 34 | * when starting the timer) |
|---|
| 37 | 35 | * HRTIMER_MODE_SOFT - Timer callback function will be executed in |
|---|
| 38 | 36 | * soft irq context |
|---|
| 37 | + * HRTIMER_MODE_HARD - Timer callback function will be executed in |
|---|
| 38 | + * hard irq context even on PREEMPT_RT. |
|---|
| 39 | 39 | */ |
|---|
| 40 | 40 | enum hrtimer_mode { |
|---|
| 41 | 41 | HRTIMER_MODE_ABS = 0x00, |
|---|
| 42 | 42 | HRTIMER_MODE_REL = 0x01, |
|---|
| 43 | 43 | HRTIMER_MODE_PINNED = 0x02, |
|---|
| 44 | 44 | HRTIMER_MODE_SOFT = 0x04, |
|---|
| 45 | + HRTIMER_MODE_HARD = 0x08, |
|---|
| 45 | 46 | |
|---|
| 46 | 47 | HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED, |
|---|
| 47 | 48 | HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED, |
|---|
| .. | .. |
|---|
| 52 | 53 | HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT, |
|---|
| 53 | 54 | HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT, |
|---|
| 54 | 55 | |
|---|
| 56 | + HRTIMER_MODE_ABS_HARD = HRTIMER_MODE_ABS | HRTIMER_MODE_HARD, |
|---|
| 57 | + HRTIMER_MODE_REL_HARD = HRTIMER_MODE_REL | HRTIMER_MODE_HARD, |
|---|
| 58 | + |
|---|
| 59 | + HRTIMER_MODE_ABS_PINNED_HARD = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_HARD, |
|---|
| 60 | + HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD, |
|---|
| 55 | 61 | }; |
|---|
| 56 | 62 | |
|---|
| 57 | 63 | /* |
|---|
| .. | .. |
|---|
| 105 | 111 | * @state: state information (See bit values above) |
|---|
| 106 | 112 | * @is_rel: Set if the timer was armed relative |
|---|
| 107 | 113 | * @is_soft: Set if hrtimer will be expired in soft interrupt context. |
|---|
| 114 | + * @is_hard: Set if hrtimer will be expired in hard interrupt context |
|---|
| 115 | + * even on RT. |
|---|
| 108 | 116 | * |
|---|
| 109 | 117 | * The hrtimer structure must be initialized by hrtimer_init() |
|---|
| 110 | 118 | */ |
|---|
| .. | .. |
|---|
| 116 | 124 | u8 state; |
|---|
| 117 | 125 | u8 is_rel; |
|---|
| 118 | 126 | u8 is_soft; |
|---|
| 127 | + u8 is_hard; |
|---|
| 119 | 128 | |
|---|
| 120 | 129 | ANDROID_KABI_RESERVE(1); |
|---|
| 121 | 130 | }; |
|---|
| .. | .. |
|---|
| 154 | 163 | struct hrtimer_cpu_base *cpu_base; |
|---|
| 155 | 164 | unsigned int index; |
|---|
| 156 | 165 | clockid_t clockid; |
|---|
| 157 | | - seqcount_t seq; |
|---|
| 166 | + seqcount_raw_spinlock_t seq; |
|---|
| 158 | 167 | struct hrtimer *running; |
|---|
| 159 | 168 | struct timerqueue_head active; |
|---|
| 160 | 169 | ktime_t (*get_time)(void); |
|---|
| .. | .. |
|---|
| 189 | 198 | * @nr_retries: Total number of hrtimer interrupt retries |
|---|
| 190 | 199 | * @nr_hangs: Total number of hrtimer interrupt hangs |
|---|
| 191 | 200 | * @max_hang_time: Maximum time spent in hrtimer_interrupt |
|---|
| 201 | + * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are |
|---|
| 202 | + * expired |
|---|
| 203 | + * @timer_waiters: A hrtimer_cancel() invocation waits for the timer |
|---|
| 204 | + * callback to finish. |
|---|
| 192 | 205 | * @expires_next: absolute time of the next event, is required for remote |
|---|
| 193 | 206 | * hrtimer enqueue; it is the total first expiry time (hard |
|---|
| 194 | 207 | * and soft hrtimer are taken into account) |
|---|
| .. | .. |
|---|
| 215 | 228 | unsigned short nr_retries; |
|---|
| 216 | 229 | unsigned short nr_hangs; |
|---|
| 217 | 230 | unsigned int max_hang_time; |
|---|
| 231 | +#endif |
|---|
| 232 | +#ifdef CONFIG_PREEMPT_RT |
|---|
| 233 | + spinlock_t softirq_expiry_lock; |
|---|
| 234 | + atomic_t timer_waiters; |
|---|
| 218 | 235 | #endif |
|---|
| 219 | 236 | ktime_t expires_next; |
|---|
| 220 | 237 | struct hrtimer *next_timer; |
|---|
| .. | .. |
|---|
| 304 | 321 | |
|---|
| 305 | 322 | extern void hrtimer_interrupt(struct clock_event_device *dev); |
|---|
| 306 | 323 | |
|---|
| 307 | | -extern void clock_was_set_delayed(void); |
|---|
| 308 | | - |
|---|
| 309 | 324 | extern unsigned int hrtimer_resolution; |
|---|
| 310 | 325 | |
|---|
| 311 | 326 | #else |
|---|
| 312 | 327 | |
|---|
| 313 | 328 | #define hrtimer_resolution (unsigned int)LOW_RES_NSEC |
|---|
| 314 | | - |
|---|
| 315 | | -static inline void clock_was_set_delayed(void) { } |
|---|
| 316 | 329 | |
|---|
| 317 | 330 | #endif |
|---|
| 318 | 331 | |
|---|
| .. | .. |
|---|
| 337 | 350 | timer->base->get_time()); |
|---|
| 338 | 351 | } |
|---|
| 339 | 352 | |
|---|
| 340 | | -extern void clock_was_set(void); |
|---|
| 341 | 353 | #ifdef CONFIG_TIMERFD |
|---|
| 342 | 354 | extern void timerfd_clock_was_set(void); |
|---|
| 343 | 355 | #else |
|---|
| .. | .. |
|---|
| 347 | 359 | |
|---|
| 348 | 360 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); |
|---|
| 349 | 361 | |
|---|
| 362 | +#ifdef CONFIG_PREEMPT_RT |
|---|
| 363 | +void hrtimer_cancel_wait_running(const struct hrtimer *timer); |
|---|
| 364 | +#else |
|---|
| 365 | +static inline void hrtimer_cancel_wait_running(struct hrtimer *timer) |
|---|
| 366 | +{ |
|---|
| 367 | + cpu_relax(); |
|---|
| 368 | +} |
|---|
| 369 | +#endif |
|---|
| 350 | 370 | |
|---|
| 351 | 371 | /* Exported timer functions: */ |
|---|
| 352 | 372 | |
|---|
| 353 | 373 | /* Initialize timers: */ |
|---|
| 354 | 374 | extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, |
|---|
| 355 | 375 | enum hrtimer_mode mode); |
|---|
| 376 | +extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id, |
|---|
| 377 | + enum hrtimer_mode mode); |
|---|
| 356 | 378 | |
|---|
| 357 | 379 | #ifdef CONFIG_DEBUG_OBJECTS_TIMERS |
|---|
| 358 | 380 | extern void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t which_clock, |
|---|
| 359 | 381 | enum hrtimer_mode mode); |
|---|
| 382 | +extern void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, |
|---|
| 383 | + clockid_t clock_id, |
|---|
| 384 | + enum hrtimer_mode mode); |
|---|
| 360 | 385 | |
|---|
| 361 | 386 | extern void destroy_hrtimer_on_stack(struct hrtimer *timer); |
|---|
| 362 | 387 | #else |
|---|
| .. | .. |
|---|
| 366 | 391 | { |
|---|
| 367 | 392 | hrtimer_init(timer, which_clock, mode); |
|---|
| 368 | 393 | } |
|---|
| 394 | + |
|---|
| 395 | +static inline void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, |
|---|
| 396 | + clockid_t clock_id, |
|---|
| 397 | + enum hrtimer_mode mode) |
|---|
| 398 | +{ |
|---|
| 399 | + hrtimer_init_sleeper(sl, clock_id, mode); |
|---|
| 400 | +} |
|---|
| 401 | + |
|---|
| 369 | 402 | static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { } |
|---|
| 370 | 403 | #endif |
|---|
| 371 | 404 | |
|---|
| .. | .. |
|---|
| 400 | 433 | delta = ktime_to_ns(ktime_sub(hard, soft)); |
|---|
| 401 | 434 | hrtimer_start_range_ns(timer, soft, delta, mode); |
|---|
| 402 | 435 | } |
|---|
| 436 | + |
|---|
| 437 | +void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, |
|---|
| 438 | + enum hrtimer_mode mode); |
|---|
| 403 | 439 | |
|---|
| 404 | 440 | static inline void hrtimer_restart(struct hrtimer *timer) |
|---|
| 405 | 441 | { |
|---|
| .. | .. |
|---|
| 471 | 507 | /* Precise sleep: */ |
|---|
| 472 | 508 | |
|---|
| 473 | 509 | extern int nanosleep_copyout(struct restart_block *, struct timespec64 *); |
|---|
| 474 | | -extern long hrtimer_nanosleep(const struct timespec64 *rqtp, |
|---|
| 475 | | - const enum hrtimer_mode mode, |
|---|
| 510 | +extern long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode, |
|---|
| 476 | 511 | const clockid_t clockid); |
|---|
| 477 | 512 | |
|---|
| 478 | | -extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, |
|---|
| 479 | | - struct task_struct *tsk); |
|---|
| 480 | | - |
|---|
| 481 | 513 | extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta, |
|---|
| 482 | | - const enum hrtimer_mode mode); |
|---|
| 514 | + const enum hrtimer_mode mode); |
|---|
| 483 | 515 | extern int schedule_hrtimeout_range_clock(ktime_t *expires, |
|---|
| 484 | 516 | u64 delta, |
|---|
| 485 | 517 | const enum hrtimer_mode mode, |
|---|