SHOW:
|
|
- or go back to the newest paste.
| 1 | diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h | |
| 2 | index bdbf77db..79a7a35 100644 | |
| 3 | --- a/include/linux/hrtimer.h | |
| 4 | +++ b/include/linux/hrtimer.h | |
| 5 | @@ -461,8 +461,9 @@ extern int schedule_hrtimeout_range_clock(ktime_t *expires, | |
| 6 | unsigned long delta, const enum hrtimer_mode mode, int clock); | |
| 7 | extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode); | |
| 8 | ||
| 9 | -/* Called from the periodic timer tick */ | |
| 10 | +/* Soft interrupt function to run the hrtimer queues: */ | |
| 11 | extern void hrtimer_run_queues(void); | |
| 12 | +extern void hrtimer_run_pending(void); | |
| 13 | ||
| 14 | /* Bootup initialization: */ | |
| 15 | extern void __init hrtimers_init(void); | |
| 16 | diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c | |
| 17 | index c19183d..c6d8232 100644 | |
| 18 | --- a/kernel/hrtimer.c | |
| 19 | +++ b/kernel/hrtimer.c | |
| 20 | @@ -1694,6 +1694,30 @@ static void run_hrtimer_softirq(struct softirq_action *h) | |
| 21 | } | |
| 22 | ||
| 23 | /* | |
| 24 | + * Called from timer softirq every jiffy, expire hrtimers: | |
| 25 | + * | |
| 26 | + * For HRT its the fall back code to run the softirq in the timer | |
| 27 | + * softirq context in case the hrtimer initialization failed or has | |
| 28 | + * not been done yet. | |
| 29 | + */ | |
| 30 | +void hrtimer_run_pending(void) | |
| 31 | +{
| |
| 32 | + if (hrtimer_hres_active()) | |
| 33 | + return; | |
| 34 | + | |
| 35 | + /* | |
| 36 | + * This _is_ ugly: We have to check in the softirq context, | |
| 37 | + * whether we can switch to highres and / or nohz mode. The | |
| 38 | + * clocksource switch happens in the timer interrupt with | |
| 39 | + * xtime_lock held. Notification from there only sets the | |
| 40 | + * check bit in the tick_oneshot code, otherwise we might | |
| 41 | + * deadlock vs. xtime_lock. | |
| 42 | + */ | |
| 43 | + if (tick_check_oneshot_change(!hrtimer_is_hres_enabled())) | |
| 44 | + hrtimer_switch_to_hres(); | |
| 45 | +} | |
| 46 | + | |
| 47 | +/* | |
| 48 | * Called from hardirq context every jiffy | |
| 49 | */ | |
| 50 | void hrtimer_run_queues(void) | |
| 51 | @@ -1706,13 +1730,6 @@ void hrtimer_run_queues(void) | |
| 52 | if (hrtimer_hres_active()) | |
| 53 | return; | |
| 54 | ||
| 55 | - /* | |
| 56 | - * Check whether we can switch to highres mode. | |
| 57 | - */ | |
| 58 | - if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()) | |
| 59 | - && hrtimer_switch_to_hres()) | |
| 60 | - return; | |
| 61 | - | |
| 62 | for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
| |
| 63 | base = &cpu_base->clock_base[index]; | |
| 64 | if (!timerqueue_getnext(&base->active)) | |
| 65 | diff --git a/kernel/timer.c b/kernel/timer.c | |
| 66 | - | index cc34e42..835b608 100644 |
| 66 | + | index cc34e42..7c523a4 100644 |
| 67 | --- a/kernel/timer.c | |
| 68 | +++ b/kernel/timer.c | |
| 69 | - | @@ -1400,7 +1400,7 @@ unsigned long get_next_timer_interrupt(unsigned long now) |
| 69 | + | |
| 70 | - | expires = base->next_timer; |
| 70 | + | |
| 71 | - | } |
| 71 | + | |
| 72 | - | #ifdef CONFIG_PREEMPT_RT_FULL |
| 72 | + | |
| 73 | + hrtimer_run_pending(); | |
| 74 | - | + rt_spin_unlock(&base->lock); |
| 74 | + | |
| 75 | - | #else |
| 75 | + | |
| 76 | - | spin_unlock(&base->lock); |
| 76 | + | |
| 77 | } | |
| 78 | @@ -1452,39 +1454,8 @@ static void run_timer_softirq(struct softirq_action *h) | |
| 79 | */ | |
| 80 | void run_local_timers(void) | |
| 81 | {
| |
| 82 | - struct tvec_base *base = __this_cpu_read(tvec_bases); | |
| 83 | - | |
| 84 | hrtimer_run_queues(); | |
| 85 | - /* | |
| 86 | - * We can access this lockless as we are in the timer | |
| 87 | - * interrupt. If there are no timers queued, nothing to do in | |
| 88 | - * the timer softirq. | |
| 89 | - */ | |
| 90 | -#ifdef CONFIG_PREEMPT_RT_FULL | |
| 91 | - /* On RT, irq work runs from softirq */ | |
| 92 | - if (irq_work_needs_cpu()) {
| |
| 93 | - raise_softirq(TIMER_SOFTIRQ); | |
| 94 | - return; | |
| 95 | - } | |
| 96 | - | |
| 97 | - if (!spin_do_trylock(&base->lock)) {
| |
| 98 | - raise_softirq(TIMER_SOFTIRQ); | |
| 99 | - return; | |
| 100 | - } | |
| 101 | -#endif | |
| 102 | - | |
| 103 | - if (!base->active_timers) | |
| 104 | - goto out; | |
| 105 | - | |
| 106 | - /* Check whether the next pending timer has expired */ | |
| 107 | - if (time_before_eq(base->next_timer, jiffies)) | |
| 108 | - raise_softirq(TIMER_SOFTIRQ); | |
| 109 | -out: | |
| 110 | -#ifdef CONFIG_PREEMPT_RT_FULL | |
| 111 | - rt_spin_unlock_after_trylock_in_irq(&base->lock); | |
| 112 | -#endif | |
| 113 | - /* The ; ensures that gcc won't complain in the !RT case */ | |
| 114 | - ; | |
| 115 | + raise_softirq(TIMER_SOFTIRQ); | |
| 116 | } | |
| 117 | ||
| 118 | #ifdef __ARCH_WANT_SYS_ALARM |