* [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call
[not found] <1399020080.5233.96.camel@marge.simpson.net>
@ 2014-05-02 11:12 ` Mike Galbraith
2014-05-06 2:37 ` Steven Rostedt
2014-05-02 11:12 ` [patch 2/6] x86/preempt-lazy adapt implementation to percpu __preempt_count Mike Galbraith
` (4 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Mike Galbraith @ 2014-05-02 11:12 UTC (permalink / raw)
To: RT; +Cc: Sebastian Andrzej Siewior, Steven Rostedt, Thomas Gleixner
__preempt_count_dec_and_test() already does it.
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
---
include/linux/preempt.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -126,8 +126,7 @@ do { \
#define preempt_enable_notrace() \
do { \
barrier(); \
- if (unlikely(__preempt_count_dec_and_test() || \
- test_thread_flag(TIF_NEED_RESCHED_LAZY))) \
+ if (unlikely(__preempt_count_dec_and_test())) \
__preempt_schedule_context(); \
} while (0)
#else
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 2/6] x86/preempt-lazy adapt implementation to percpu __preempt_count
[not found] <1399020080.5233.96.camel@marge.simpson.net>
2014-05-02 11:12 ` [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call Mike Galbraith
@ 2014-05-02 11:12 ` Mike Galbraith
2014-05-02 11:13 ` [patch 3/6] stomp-machine: fix typo in kernel/cpu.c Mike Galbraith
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Mike Galbraith @ 2014-05-02 11:12 UTC (permalink / raw)
To: RT; +Cc: Sebastian Andrzej Siewior, Steven Rostedt, Thomas Gleixner
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
---
arch/x86/include/asm/preempt.h | 8 ++++++++
arch/x86/kernel/asm-offsets.c | 1 +
arch/x86/kernel/entry_32.S | 9 ++++++---
arch/x86/kernel/entry_64.S | 7 +++++--
4 files changed, 20 insertions(+), 5 deletions(-)
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -94,7 +94,11 @@ static __always_inline bool __preempt_co
{
if (____preempt_count_dec_and_test())
return true;
+#ifdef CONFIG_PREEMPT_LAZY
return test_thread_flag(TIF_NEED_RESCHED_LAZY);
+#else
+ return false;
+#endif
}
/*
@@ -102,8 +106,12 @@ static __always_inline bool __preempt_co
*/
static __always_inline bool should_resched(void)
{
+#ifdef CONFIG_PREEMPT_LAZY
return unlikely(!__this_cpu_read_4(__preempt_count) || \
test_thread_flag(TIF_NEED_RESCHED_LAZY));
+#else
+ return unlikely(!__this_cpu_read_4(__preempt_count));
+#endif
}
#ifdef CONFIG_PREEMPT
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -72,4 +72,5 @@ void common(void) {
BLANK();
DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
+ DEFINE(_PREEMPT_ENABLED, PREEMPT_ENABLED);
}
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -365,19 +365,22 @@ ENTRY(resume_kernel)
need_resched:
# preempt count == 0 + NEED_RS set?
cmpl $0,PER_CPU_VAR(__preempt_count)
+#ifndef CONFIG_PREEMPT_LAZY
+ jnz restore_all
+#else
jz test_int_off
# atleast preempt count == 0 ?
- cmpl $_TIF_NEED_RESCHED,PER_CPU_VAR(__preempt_count)
+ cmpl $_PREEMPT_ENABLED,PER_CPU_VAR(__preempt_count)
jne restore_all
cmpl $0,TI_preempt_lazy_count(%ebp) # non-zero preempt_lazy_count ?
jnz restore_all
- testl $_TIF_NEED_RESCHED_LAZY, %ecx
+ testl $_TIF_NEED_RESCHED_LAZY, TI_flags(%ebp)
jz restore_all
-
test_int_off:
+#endif
testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
call preempt_schedule_irq
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1104,10 +1104,13 @@ ENTRY(native_iret)
/* rcx: threadinfo. interrupts off. */
ENTRY(retint_kernel)
cmpl $0,PER_CPU_VAR(__preempt_count)
+#ifndef CONFIG_PREEMPT_LAZY
+ jnz retint_restore_args
+#else
jz check_int_off
# atleast preempt count == 0 ?
- cmpl $_TIF_NEED_RESCHED,PER_CPU_VAR(__preempt_count)
+ cmpl $_PREEMPT_ENABLED,PER_CPU_VAR(__preempt_count)
jnz retint_restore_args
cmpl $0, TI_preempt_lazy_count(%rcx)
@@ -1115,8 +1118,8 @@ ENTRY(retint_kernel)
bt $TIF_NEED_RESCHED_LAZY,TI_flags(%rcx)
jnc retint_restore_args
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 3/6] stomp-machine: fix typo in kernel/cpu.c
[not found] <1399020080.5233.96.camel@marge.simpson.net>
2014-05-02 11:12 ` [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call Mike Galbraith
2014-05-02 11:12 ` [patch 2/6] x86/preempt-lazy adapt implementation to percpu __preempt_count Mike Galbraith
@ 2014-05-02 11:13 ` Mike Galbraith
2014-05-02 11:13 ` [patch 4/6] stomp-machine: fix typo in kernel/stop_machine.c Mike Galbraith
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Mike Galbraith @ 2014-05-02 11:13 UTC (permalink / raw)
To: RT; +Cc: Sebastian Andrzej Siewior, Steven Rostedt, Thomas Gleixner
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
---
kernel/cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -649,7 +649,7 @@ static int __ref _cpu_down(unsigned int
/* CPU didn't die: tell everyone. Can't complain. */
smpboot_unpark_threads(cpu);
cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);
- goto out_cancel;
+ goto out_release;
}
BUG_ON(cpu_online(cpu));
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 4/6] stomp-machine: fix typo in kernel/stop_machine.c
[not found] <1399020080.5233.96.camel@marge.simpson.net>
` (2 preceding siblings ...)
2014-05-02 11:13 ` [patch 3/6] stomp-machine: fix typo in kernel/cpu.c Mike Galbraith
@ 2014-05-02 11:13 ` Mike Galbraith
2014-05-02 11:13 ` [patch 5/6] stomp-machine: create lg_global_trylock_relax() primitive Mike Galbraith
2014-05-02 11:13 ` [patch 6/6] stomp-machine: use lg_global_trylock_relax() to dead with stop_cpus_lock lglock Mike Galbraith
5 siblings, 0 replies; 9+ messages in thread
From: Mike Galbraith @ 2014-05-02 11:13 UTC (permalink / raw)
To: RT; +Cc: Sebastian Andrzej Siewior, Steven Rostedt, Thomas Gleixner
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
---
kernel/stop_machine.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -671,7 +671,7 @@ int stop_machine_from_inactive_cpu(int (
ret = multi_cpu_stop(&msdata);
/* Busy wait for completion. */
- while (!atomic_read(&done.nr_todo))
+ while (atomic_read(&done.nr_todo))
cpu_relax();
mutex_unlock(&stop_cpus_mutex);
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 5/6] stomp-machine: create lg_global_trylock_relax() primitive
[not found] <1399020080.5233.96.camel@marge.simpson.net>
` (3 preceding siblings ...)
2014-05-02 11:13 ` [patch 4/6] stomp-machine: fix typo in kernel/stop_machine.c Mike Galbraith
@ 2014-05-02 11:13 ` Mike Galbraith
2014-05-02 11:13 ` [patch 6/6] stomp-machine: use lg_global_trylock_relax() to dead with stop_cpus_lock lglock Mike Galbraith
5 siblings, 0 replies; 9+ messages in thread
From: Mike Galbraith @ 2014-05-02 11:13 UTC (permalink / raw)
To: RT; +Cc: Sebastian Andrzej Siewior, Steven Rostedt, Thomas Gleixner
Create lg_global_trylock_relax() for use by stopper thread when it cannot
schedule, to deal with stop_cpus_lock, which is now an lglock.
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
---
include/linux/lglock.h | 6 ++++++
include/linux/spinlock_rt.h | 1 +
kernel/locking/lglock.c | 25 +++++++++++++++++++++++++
kernel/locking/rtmutex.c | 5 +++++
4 files changed, 37 insertions(+)
--- a/include/linux/lglock.h
+++ b/include/linux/lglock.h
@@ -74,4 +74,10 @@ void lg_local_unlock_cpu(struct lglock *
void lg_global_lock(struct lglock *lg);
void lg_global_unlock(struct lglock *lg);
+#ifndef CONFIG_PREEMPT_RT_FULL
+#define lg_global_trylock_relax(name) lg_global_lock(name)
+#else
+void lg_global_trylock_relax(struct lglock *lg);
+#endif
+
#endif
--- a/include/linux/spinlock_rt.h
+++ b/include/linux/spinlock_rt.h
@@ -35,6 +35,7 @@ extern int atomic_dec_and_spin_lock(atom
*/
extern void __lockfunc __rt_spin_lock(struct rt_mutex *lock);
extern void __lockfunc __rt_spin_unlock(struct rt_mutex *lock);
+extern int __lockfunc __rt_spin_trylock(struct rt_mutex *lock);
#define spin_lock(lock) \
do { \
--- a/kernel/locking/lglock.c
+++ b/kernel/locking/lglock.c
@@ -105,3 +105,28 @@ void lg_global_unlock(struct lglock *lg)
preempt_enable_nort();
}
EXPORT_SYMBOL(lg_global_unlock);
+
+#ifdef CONFIG_PREEMPT_RT_FULL
+/*
+ * HACK: If you use this, you get to keep the pieces.
+ * Used in queue_stop_cpus_work() when stop machinery
+ * is called from inactive CPU, so we can't schedule.
+ */
+# define lg_do_trylock_relax(l) \
+ do { \
+ while (!__rt_spin_trylock(l)) \
+ cpu_relax(); \
+ } while (0)
+
+void lg_global_trylock_relax(struct lglock *lg)
+{
+ int i;
+
+ lock_acquire_exclusive(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
+ for_each_possible_cpu(i) {
+ lg_lock_ptr *lock;
+ lock = per_cpu_ptr(lg->lock, i);
+ lg_do_trylock_relax(lock);
+ }
+}
+#endif
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1001,6 +1001,11 @@ void __lockfunc rt_spin_unlock_wait(spin
}
EXPORT_SYMBOL(rt_spin_unlock_wait);
+int __lockfunc __rt_spin_trylock(struct rt_mutex *lock)
+{
+ return rt_mutex_trylock(lock);
+}
+
int __lockfunc rt_spin_trylock(spinlock_t *lock)
{
int ret = rt_mutex_trylock(&lock->lock);
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 6/6] stomp-machine: use lg_global_trylock_relax() to dead with stop_cpus_lock lglock
[not found] <1399020080.5233.96.camel@marge.simpson.net>
` (4 preceding siblings ...)
2014-05-02 11:13 ` [patch 5/6] stomp-machine: create lg_global_trylock_relax() primitive Mike Galbraith
@ 2014-05-02 11:13 ` Mike Galbraith
5 siblings, 0 replies; 9+ messages in thread
From: Mike Galbraith @ 2014-05-02 11:13 UTC (permalink / raw)
To: RT; +Cc: Sebastian Andrzej Siewior, Steven Rostedt, Thomas Gleixner
If the stop machinery is called from inactive CPU we cannot use
lg_global_lock(), because some other stomp machine invocation might be
in progress and the lock can be contended. We cannot schedule from this
context, so use the lovely new lg_global_trylock_relax() primitive to
do what we used to do via one mutex_trylock()/cpu_relax() loop. We
now do that trylock()/relax() across an entire herd of locks. Joy.
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
---
kernel/stop_machine.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -266,7 +266,7 @@ int stop_two_cpus(unsigned int cpu1, uns
struct irq_cpu_stop_queue_work_info call_args;
struct multi_stop_data msdata;
- preempt_disable();
+ preempt_disable_nort();
msdata = (struct multi_stop_data){
.fn = fn,
.data = arg,
@@ -299,7 +299,7 @@ int stop_two_cpus(unsigned int cpu1, uns
* This relies on the stopper workqueues to be FIFO.
*/
if (!cpu_active(cpu1) || !cpu_active(cpu2)) {
- preempt_enable();
+ preempt_enable_nort();
return -ENOENT;
}
@@ -313,7 +313,7 @@ int stop_two_cpus(unsigned int cpu1, uns
&irq_cpu_stop_queue_work,
&call_args, 1);
lg_local_unlock(&stop_cpus_lock);
- preempt_enable();
+ preempt_enable_nort();
wait_for_stop_done(&done);
@@ -346,7 +346,7 @@ static DEFINE_PER_CPU(struct cpu_stop_wo
static void queue_stop_cpus_work(const struct cpumask *cpumask,
cpu_stop_fn_t fn, void *arg,
- struct cpu_stop_done *done)
+ struct cpu_stop_done *done, bool inactive)
{
struct cpu_stop_work *work;
unsigned int cpu;
@@ -360,11 +360,13 @@ static void queue_stop_cpus_work(const s
}
/*
- * Disable preemption while queueing to avoid getting
- * preempted by a stopper which might wait for other stoppers
- * to enter @fn which can lead to deadlock.
+ * Make sure that all work is queued on all cpus before
+ * any of the cpus can execute it.
*/
- lg_global_lock(&stop_cpus_lock);
+ if (!inactive)
+ lg_global_lock(&stop_cpus_lock);
+ else
+ lg_global_trylock_relax(&stop_cpus_lock);
for_each_cpu(cpu, cpumask)
cpu_stop_queue_work(cpu, &per_cpu(stop_cpus_work, cpu));
lg_global_unlock(&stop_cpus_lock);
@@ -376,7 +378,7 @@ static int __stop_cpus(const struct cpum
struct cpu_stop_done done;
cpu_stop_init_done(&done, cpumask_weight(cpumask));
- queue_stop_cpus_work(cpumask, fn, arg, &done);
+ queue_stop_cpus_work(cpumask, fn, arg, &done, false);
wait_for_stop_done(&done);
return done.executed ? done.ret : -ENOENT;
}
@@ -572,6 +574,8 @@ static int __init cpu_stop_init(void)
INIT_LIST_HEAD(&stopper->works);
}
+ lg_lock_init(&stop_cpus_lock, "stop_cpus_lock");
+
BUG_ON(smpboot_register_percpu_thread(&cpu_stop_threads));
stop_machine_initialized = true;
return 0;
@@ -667,7 +671,7 @@ int stop_machine_from_inactive_cpu(int (
set_state(&msdata, MULTI_STOP_PREPARE);
cpu_stop_init_done(&done, num_active_cpus());
queue_stop_cpus_work(cpu_active_mask, multi_cpu_stop, &msdata,
- &done);
+ &done, true);
ret = multi_cpu_stop(&msdata);
/* Busy wait for completion. */
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call
2014-05-02 11:12 ` [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call Mike Galbraith
@ 2014-05-06 2:37 ` Steven Rostedt
2014-05-06 5:33 ` Mike Galbraith
0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2014-05-06 2:37 UTC (permalink / raw)
To: Mike Galbraith; +Cc: RT, Sebastian Andrzej Siewior, Thomas Gleixner
On Fri, 02 May 2014 13:12:46 +0200
Mike Galbraith <umgwanakikbuti@gmail.com> wrote:
> __preempt_count_dec_and_test() already does it.
Already does what? :-)
Hmm, do all archs check? Perhaps we need to also update
include/asm-generic/preempt.h?
-- Steve
>
> Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
> ---
> include/linux/preempt.h | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> --- a/include/linux/preempt.h
> +++ b/include/linux/preempt.h
> @@ -126,8 +126,7 @@ do { \
> #define preempt_enable_notrace() \
> do { \
> barrier(); \
> - if (unlikely(__preempt_count_dec_and_test() || \
> - test_thread_flag(TIF_NEED_RESCHED_LAZY))) \
> + if (unlikely(__preempt_count_dec_and_test())) \
> __preempt_schedule_context(); \
> } while (0)
> #else
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call
2014-05-06 2:37 ` Steven Rostedt
@ 2014-05-06 5:33 ` Mike Galbraith
2014-05-09 13:17 ` Sebastian Andrzej Siewior
0 siblings, 1 reply; 9+ messages in thread
From: Mike Galbraith @ 2014-05-06 5:33 UTC (permalink / raw)
To: Steven Rostedt; +Cc: RT, Sebastian Andrzej Siewior, Thomas Gleixner
On Mon, 2014-05-05 at 22:37 -0400, Steven Rostedt wrote:
> On Fri, 02 May 2014 13:12:46 +0200
> Mike Galbraith <umgwanakikbuti@gmail.com> wrote:
>
> > __preempt_count_dec_and_test() already does it.
>
> Already does what? :-)
Poo.. yeah that.
> Hmm, do all archs check? Perhaps we need to also update
> include/asm-generic/preempt.h?
Per cpu preempt_count is x86, and tif_need_resched() handles laziness,
so all should be well. Did I just manage to overlook the obvious for
the second time?
-Mike
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call
2014-05-06 5:33 ` Mike Galbraith
@ 2014-05-09 13:17 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 9+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-05-09 13:17 UTC (permalink / raw)
To: Mike Galbraith; +Cc: Steven Rostedt, RT, Thomas Gleixner
* Mike Galbraith | 2014-05-06 07:33:51 [+0200]:
>> Hmm, do all archs check? Perhaps we need to also update
>> include/asm-generic/preempt.h?
>
>Per cpu preempt_count is x86, and tif_need_resched() handles laziness,
>so all should be well. Did I just manage to overlook the obvious for
>the second time?
In include/asm-generic/preempt.h we have
| static __always_inline bool __preempt_count_dec_and_test(void)
| {
| return !--*preempt_count_ptr() && tif_need_resched();
| }
and tif_need_resched() is in include/linux/thread_info.h
| #ifdef CONFIG_PREEMPT_LAZY
| #define tif_need_resched() (test_thread_flag(TIF_NEED_RESCHED) || \
| test_thread_flag(TIF_NEED_RESCHED_LAZY))
| #else
| #define tif_need_resched() (test_thread_flag(TIF_NEED_RESCHED))
| #endif
So I guess we are fine.
>-Mike
Sebastian
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-05-09 13:17 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1399020080.5233.96.camel@marge.simpson.net>
2014-05-02 11:12 ` [patch 1/6] preempt_lazy: remove redundant test_thread_flag() call Mike Galbraith
2014-05-06 2:37 ` Steven Rostedt
2014-05-06 5:33 ` Mike Galbraith
2014-05-09 13:17 ` Sebastian Andrzej Siewior
2014-05-02 11:12 ` [patch 2/6] x86/preempt-lazy adapt implementation to percpu __preempt_count Mike Galbraith
2014-05-02 11:13 ` [patch 3/6] stomp-machine: fix typo in kernel/cpu.c Mike Galbraith
2014-05-02 11:13 ` [patch 4/6] stomp-machine: fix typo in kernel/stop_machine.c Mike Galbraith
2014-05-02 11:13 ` [patch 5/6] stomp-machine: create lg_global_trylock_relax() primitive Mike Galbraith
2014-05-02 11:13 ` [patch 6/6] stomp-machine: use lg_global_trylock_relax() to dead with stop_cpus_lock lglock Mike Galbraith
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).