All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.