Skip to content

Commit a3eb76a

Browse files
KAGA-KOKOgratian
authored andcommitted
rt: Introduce cpu_chill()
Retry loops on RT might loop forever when the modifying side was preempted. Add cpu_chill() to replace cpu_relax(). cpu_chill() defaults to cpu_relax() for non RT. On RT it puts the looping task to sleep for a tick so the preempted task can make progress. Steven Rostedt changed it to use a hrtimer instead of msleep(): | |Ulrich Obergfell pointed out that cpu_chill() calls msleep() which is woken |up by the ksoftirqd running the TIMER softirq. But as the cpu_chill() is |called from softirq context, it may block the ksoftirqd() from running, in |which case, it may never wake up the msleep() causing the deadlock. + bigeasy later changed to schedule_hrtimeout() |If a task calls cpu_chill() and gets woken up by a regular or spurious |wakeup and has a signal pending, then it exits the sleep loop in |do_nanosleep() and sets up the restart block. If restart->nanosleep.type is |not TI_NONE then this results in accessing a stale user pointer from a |previously interrupted syscall and a copy to user based on the stale |pointer or a BUG() when 'type' is not supported in nanosleep_copyout(). + bigeasy: add PF_NOFREEZE: | [....] Waiting for /dev to be fully populated... | ===================================== | [ BUG: udevd/229 still has locks held! ] | 3.12.11-rt17 ni#23 Not tainted | ------------------------------------- | 1 lock held by udevd/229: | #0: (&type->i_mutex_dir_key#2){+.+.+.}, at: lookup_slow+0x28/0x98 | | stack backtrace: | CPU: 0 PID: 229 Comm: udevd Not tainted 3.12.11-rt17 ni#23 | (unwind_backtrace+0x0/0xf8) from (show_stack+0x10/0x14) | (show_stack+0x10/0x14) from (dump_stack+0x74/0xbc) | (dump_stack+0x74/0xbc) from (do_nanosleep+0x120/0x160) | (do_nanosleep+0x120/0x160) from (hrtimer_nanosleep+0x90/0x110) | (hrtimer_nanosleep+0x90/0x110) from (cpu_chill+0x30/0x38) | (cpu_chill+0x30/0x38) from (dentry_kill+0x158/0x1ec) | (dentry_kill+0x158/0x1ec) from (dput+0x74/0x15c) | (dput+0x74/0x15c) from (lookup_real+0x4c/0x50) | (lookup_real+0x4c/0x50) from (__lookup_hash+0x34/0x44) | (__lookup_hash+0x34/0x44) from (lookup_slow+0x38/0x98) | (lookup_slow+0x38/0x98) from (path_lookupat+0x208/0x7fc) | (path_lookupat+0x208/0x7fc) from (filename_lookup+0x20/0x60) | (filename_lookup+0x20/0x60) from (user_path_at_empty+0x50/0x7c) | (user_path_at_empty+0x50/0x7c) from (user_path_at+0x14/0x1c) | (user_path_at+0x14/0x1c) from (vfs_fstatat+0x48/0x94) | (vfs_fstatat+0x48/0x94) from (SyS_stat64+0x14/0x30) | (SyS_stat64+0x14/0x30) from (ret_fast_syscall+0x0/0x48) Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent f6ce879 commit a3eb76a

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

include/linux/hrtimer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum hrtimer_mode {
4242
HRTIMER_MODE_PINNED = 0x02,
4343
HRTIMER_MODE_SOFT = 0x04,
4444
HRTIMER_MODE_HARD = 0x08,
45+
HRTIMER_MODE_CHILL = 0x10,
4546

4647
HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED,
4748
HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED,
@@ -124,6 +125,7 @@ struct hrtimer {
124125
u8 is_rel;
125126
u8 is_soft;
126127
u8 is_hard;
128+
u8 is_chill;
127129
};
128130

129131
/**
@@ -536,4 +538,10 @@ int hrtimers_dead_cpu(unsigned int cpu);
536538
#define hrtimers_dead_cpu NULL
537539
#endif
538540

541+
#ifdef CONFIG_PREEMPT_RT
542+
extern void cpu_chill(void);
543+
#else
544+
# define cpu_chill() cpu_relax()
545+
#endif
546+
539547
#endif

kernel/time/hrtimer.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
15701570
base += hrtimer_clockid_to_base(clock_id);
15711571
timer->is_soft = softtimer;
15721572
timer->is_hard = !!(mode & HRTIMER_MODE_HARD);
1573+
timer->is_chill = !!(mode & HRTIMER_MODE_CHILL);
15731574
timer->base = &cpu_base->clock_base[base];
15741575
timerqueue_init(&timer->node);
15751576
}
@@ -1936,7 +1937,7 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer)
19361937

19371938
t->task = NULL;
19381939
if (task)
1939-
wake_up_process(task);
1940+
wake_up_state(task, timer->is_chill ? TASK_RTLOCK_WAIT : TASK_NORMAL);
19401941

19411942
return HRTIMER_NORESTART;
19421943
}
@@ -2156,6 +2157,34 @@ SYSCALL_DEFINE2(nanosleep_time32, struct old_timespec32 __user *, rqtp,
21562157
}
21572158
#endif
21582159

2160+
#ifdef CONFIG_PREEMPT_RT
2161+
/*
2162+
* Sleep for 1 ms in hope whoever holds what we want will let it go.
2163+
*/
2164+
void cpu_chill(void)
2165+
{
2166+
unsigned int freeze_flag = current->flags & PF_NOFREEZE;
2167+
ktime_t chill_time;
2168+
2169+
local_irq_disable();
2170+
current_save_and_set_rtlock_wait_state();
2171+
local_irq_enable();
2172+
2173+
chill_time = ktime_set(0, NSEC_PER_MSEC);
2174+
2175+
current->flags |= PF_NOFREEZE;
2176+
schedule_hrtimeout(&chill_time,
2177+
HRTIMER_MODE_REL_HARD| HRTIMER_MODE_CHILL);
2178+
if (!freeze_flag)
2179+
current->flags &= ~PF_NOFREEZE;
2180+
2181+
local_irq_disable();
2182+
current_restore_rtlock_saved_state();
2183+
local_irq_enable();
2184+
}
2185+
EXPORT_SYMBOL(cpu_chill);
2186+
#endif
2187+
21592188
/*
21602189
* Functions related to boot-time initialization:
21612190
*/

0 commit comments

Comments
 (0)