diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 0ee140176f102..4a2230e409d2a 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -42,6 +42,7 @@ enum hrtimer_mode { HRTIMER_MODE_PINNED = 0x02, HRTIMER_MODE_SOFT = 0x04, HRTIMER_MODE_HARD = 0x08, + HRTIMER_MODE_CHILL = 0x10, HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED, HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED, @@ -124,6 +125,7 @@ struct hrtimer { u8 is_rel; u8 is_soft; u8 is_hard; + u8 is_chill; }; /** @@ -536,4 +538,10 @@ int hrtimers_dead_cpu(unsigned int cpu); #define hrtimers_dead_cpu NULL #endif +#ifdef CONFIG_PREEMPT_RT +extern void cpu_chill(void); +#else +# define cpu_chill() cpu_relax() +#endif + #endif diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 0ea8702eb5163..295e065d27905 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1570,6 +1570,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, base += hrtimer_clockid_to_base(clock_id); timer->is_soft = softtimer; timer->is_hard = !!(mode & HRTIMER_MODE_HARD); + timer->is_chill = !!(mode & HRTIMER_MODE_CHILL); timer->base = &cpu_base->clock_base[base]; timerqueue_init(&timer->node); } @@ -1936,7 +1937,7 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer) t->task = NULL; if (task) - wake_up_process(task); + wake_up_state(task, timer->is_chill ? TASK_RTLOCK_WAIT : TASK_NORMAL); return HRTIMER_NORESTART; } @@ -2154,6 +2155,34 @@ SYSCALL_DEFINE2(nanosleep_time32, struct old_timespec32 __user *, rqtp, } #endif +#ifdef CONFIG_PREEMPT_RT +/* + * Sleep for 1 ms in hope whoever holds what we want will let it go. + */ +void cpu_chill(void) +{ + unsigned int freeze_flag = current->flags & PF_NOFREEZE; + ktime_t chill_time; + + local_irq_disable(); + current_save_and_set_rtlock_wait_state(); + local_irq_enable(); + + chill_time = ktime_set(0, NSEC_PER_MSEC); + + current->flags |= PF_NOFREEZE; + schedule_hrtimeout(&chill_time, + HRTIMER_MODE_REL_HARD| HRTIMER_MODE_CHILL); + if (!freeze_flag) + current->flags &= ~PF_NOFREEZE; + + local_irq_disable(); + current_restore_rtlock_saved_state(); + local_irq_enable(); +} +EXPORT_SYMBOL(cpu_chill); +#endif + /* * Functions related to boot-time initialization: */