public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* RE: [BUG] Variable stopmachine_state should be volatile
@ 2005-12-08  1:37 Zhang, Yanmin
  2005-12-12 13:39 ` Christoph Hellwig
  0 siblings, 1 reply; 13+ messages in thread
From: Zhang, Yanmin @ 2005-12-08  1:37 UTC (permalink / raw)
  To: Arjan van de Ven, Pavel Machek
  Cc: linux-kernel, Pallipadi, Venkatesh, Shah, Rajesh, linux-ia64

>>-----Original Message-----
>>From: Arjan van de Ven [mailto:arjan@infradead.org]
>>Sent: 2005年12月2日 16:04
>>To: Zhang, Yanmin
>>Cc: linux-kernel@vger.kernel.org; Pallipadi, Venkatesh; Shah, Rajesh
>>Subject: Re: [BUG] Variable stopmachine_state should be volatile
>>
>>On Wed, 2005-11-30 at 10:04 +0800, Zhang, Yanmin wrote:
>>> The model to access variable stopmachine_state is that a main thread
>>> writes it and other threads read it. Its declaration has no sign
>>> volatile. In the while loop in function stopmachine, this variable is
>>> read, and compiler might optimize it by reading it once before the loop
>>> and not reading it again in the loop, so the thread might enter dead
>>> loop.
>>
>>cpu_relax() includes a compiler barier..... so... what's wrong with the
>>compiler that it ignores such barriers?

You are right. I hit the problem when I compiled kernel 2.6.9 on IA64 by intel compiler.
cpu_relax has the compiler barrier if we use gcc, but cpu_relax becomes just ia64_hint which is null when I use intel compiler to compile kernel on ia64. file include/asm-ia64/intel_intrin.h defines ia64_hint as null.

Function stopmachine in kernel/stop_machine.c uses cpu_relax to prevent compiler from moving the reading of stopmachine_state out of the while loop. But when we use intel compiler, cpu_relax doesn't work because it is just null.

The right approach is to define ia64_hint to ia64_barrier in file include/asm-ia64/intel_intrin.h. I tested the new approach and it does work.

Thank Arjan, Pavel, and Venki.


^ permalink raw reply	[flat|nested] 13+ messages in thread
* RE: [BUG] Variable stopmachine_state should be volatile
@ 2005-12-12  7:06 Zhang, Yanmin
  0 siblings, 0 replies; 13+ messages in thread
From: Zhang, Yanmin @ 2005-12-12  7:06 UTC (permalink / raw)
  To: Luck, Tony, Arjan van de Ven, Pavel Machek
  Cc: linux-kernel, Pallipadi, Venkatesh, Shah, Rajesh, linux-ia64

>>-----Original Message-----
>>From: linux-ia64-owner@vger.kernel.org
>>[mailto:linux-ia64-owner@vger.kernel.org] On Behalf Of Luck, Tony
>>Sent: 2005年12月9日 2:53
>>To: Zhang, Yanmin; Arjan van de Ven; Pavel Machek
>>Cc: linux-kernel@vger.kernel.org; Pallipadi, Venkatesh; Shah, Rajesh;
>>linux-ia64@vger.kernel.org
>>Subject: RE: [BUG] Variable stopmachine_state should be volatile
>>
>>> The right approach is to define ia64_hint to ia64_barrier in file
>>> include/asm-ia64/intel_intrin.h. I tested the new approach and it
>>> does work.
>>
>>Does that get you a "hint@pause" instruction inside the loop?  If not, then
>>it isn't all the way to the "right" approach.

Tony,

The approach just fixes compiler scheduling barrier problem of cpu_relax, and there is no hint@pause inside the loop.

Today I tried the latest icc, 9.0.027. It provides __hint, a new intrinsic, to support hint@pause. __hint also has the meaning of compiler scheduling barrier. So the best solution is to use __hint(0). The disassembled result showed the new intrinsic did work.


^ permalink raw reply	[flat|nested] 13+ messages in thread
* RE: [BUG] Variable stopmachine_state should be volatile
@ 2005-12-08 18:53 Luck, Tony
  0 siblings, 0 replies; 13+ messages in thread
From: Luck, Tony @ 2005-12-08 18:53 UTC (permalink / raw)
  To: Zhang, Yanmin, Arjan van de Ven, Pavel Machek
  Cc: linux-kernel, Pallipadi, Venkatesh, Shah, Rajesh, linux-ia64

> The right approach is to define ia64_hint to ia64_barrier in file
> include/asm-ia64/intel_intrin.h. I tested the new approach and it
> does work.

Does that get you a "hint@pause" instruction inside the loop?  If not, then
it isn't all the way to the "right" approach.

-Tony

^ permalink raw reply	[flat|nested] 13+ messages in thread
[parent not found: <88056F38E9E48644A0F562A38C64FB60067BE61C@scsmsx403.amr.corp.intel.com>]
* RE: [BUG] Variable stopmachine_state should be volatile
@ 2005-12-02  2:48 Zhang, Yanmin
  0 siblings, 0 replies; 13+ messages in thread
From: Zhang, Yanmin @ 2005-12-02  2:48 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel, Pallipadi, Venkatesh, Shah, Rajesh

[-- Attachment #1: Type: text/plain, Size: 731 bytes --]

>>-----Original Message-----
>>From: Pavel Machek [mailto:pavel@ucw.cz]
>>Sent: 2005年12月1日 18:26
>>To: Zhang, Yanmin
>>Cc: linux-kernel@vger.kernel.org; Pallipadi, Venkatesh; Shah, Rajesh
>>Subject: Re: [BUG] Variable stopmachine_state should be volatile
>>
>>Hi!
>>
>>> >>Those barriers should already prevent compiler optimalization, no? If
>>> >>they do not, just use some barriers that do.
>>>
>>>
>>> I hit the problem when compiling 2.6 kernel by intel compiler.
>>> How about to change the type of stopmachine_state to atomic_t?
>>
>>That is certainly safest / very conservative solution.
>>								Pavel
Thanks. The functions are not performance sensitive, so atomic_t is ok. Here is the new patch.


[-- Attachment #2: stopmachine_state_volatile_2.6.15_rc3_v2.patch --]
[-- Type: application/octet-stream, Size: 2708 bytes --]

--- linux-2.6.15-rc3/kernel/stop_machine.c	2005-11-29 00:02:44.000000000 +0800
+++ linux-2.6.15-rc3_fix/kernel/stop_machine.c	2005-11-30 18:41:55.000000000 +0800
@@ -13,14 +13,12 @@
  * kthread. */
 
 /* Thread to stop each CPU in user context. */
-enum stopmachine_state {
-	STOPMACHINE_WAIT,
-	STOPMACHINE_PREPARE,
-	STOPMACHINE_DISABLE_IRQ,
-	STOPMACHINE_EXIT,
-};
+#define	STOPMACHINE_WAIT		0
+#define	STOPMACHINE_PREPARE		1
+#define	STOPMACHINE_DISABLE_IRQ		2
+#define	STOPMACHINE_EXIT		3
 
-static enum stopmachine_state stopmachine_state;
+static atomic_t stopmachine_state;
 static unsigned int stopmachine_num_threads;
 static atomic_t stopmachine_thread_ack;
 static DECLARE_MUTEX(stopmachine_mutex);
@@ -33,24 +31,21 @@ static int stopmachine(void *cpu)
 	set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
 
 	/* Ack: we are alive */
-	smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
 	atomic_inc(&stopmachine_thread_ack);
 
 	/* Simple state machine */
-	while (stopmachine_state != STOPMACHINE_EXIT) {
-		if (stopmachine_state == STOPMACHINE_DISABLE_IRQ 
+	while (atomic_read(&stopmachine_state) != STOPMACHINE_EXIT) {
+		if (atomic_read(&stopmachine_state) == STOPMACHINE_DISABLE_IRQ 
 		    && !irqs_disabled) {
 			local_irq_disable();
 			irqs_disabled = 1;
 			/* Ack: irqs disabled. */
-			smp_mb(); /* Must read state first. */
 			atomic_inc(&stopmachine_thread_ack);
-		} else if (stopmachine_state == STOPMACHINE_PREPARE
-			   && !prepared) {
+		} else if (atomic_read(&stopmachine_state)
+				== STOPMACHINE_PREPARE && !prepared) {
 			/* Everyone is in place, hold CPU. */
 			preempt_disable();
 			prepared = 1;
-			smp_mb(); /* Must read state first. */
 			atomic_inc(&stopmachine_thread_ack);
 		}
 		/* Yield in first stage: migration threads need to
@@ -62,7 +57,6 @@ static int stopmachine(void *cpu)
 	}
 
 	/* Ack: we are exiting. */
-	smp_mb(); /* Must read state first. */
 	atomic_inc(&stopmachine_thread_ack);
 
 	if (irqs_disabled)
@@ -74,11 +68,10 @@ static int stopmachine(void *cpu)
 }
 
 /* Change the thread state */
-static void stopmachine_set_state(enum stopmachine_state state)
+static void stopmachine_set_state(int state)
 {
 	atomic_set(&stopmachine_thread_ack, 0);
-	smp_wmb();
-	stopmachine_state = state;
+	atomic_set(&stopmachine_state, state);
 	while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads)
 		cpu_relax();
 }
@@ -97,7 +90,7 @@ static int stop_machine(void)
 
 	atomic_set(&stopmachine_thread_ack, 0);
 	stopmachine_num_threads = 0;
-	stopmachine_state = STOPMACHINE_WAIT;
+	atomic_set(&stopmachine_state, STOPMACHINE_WAIT);
 
 	for_each_online_cpu(i) {
 		if (i == raw_smp_processor_id())

^ permalink raw reply	[flat|nested] 13+ messages in thread
* RE: [BUG] Variable stopmachine_state should be volatile
@ 2005-12-01  5:27 Zhang, Yanmin
  2005-12-01 10:26 ` Pavel Machek
  0 siblings, 1 reply; 13+ messages in thread
From: Zhang, Yanmin @ 2005-12-01  5:27 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel, Pallipadi, Venkatesh, Shah, Rajesh

>>-----Original Message-----
>>From: Pavel Machek [mailto:pavel@ucw.cz]
>>Sent: 2005年12月1日 11:26
>>To: Zhang, Yanmin
>>Cc: linux-kernel@vger.kernel.org; Pallipadi, Venkatesh; Shah, Rajesh
>>Subject: Re: [BUG] Variable stopmachine_state should be volatile
>>
>>Hi!
>>
>>> >>Hi!
>>> >>
>>> >>> The model to access variable stopmachine_state is that a main thread
>>> >>> writes it and other threads read it. Its declaration has no sign
>>> >>> volatile. In the while loop in function stopmachine, this variable is
>>> >>> read, and compiler might optimize it by reading it once before the loop
>>> >>> and not reading it again in the loop, so the thread might enter dead
>>> >>> loop.
>>> >>
>>> >>No. volatile may look like a solution, but it usually is not. You may
>>> >>need some barriers, atomic_t or locking.
>>> >>								Pavel
>>> The original functions already use smp_mb/smp_wmb. My patch just
>>>tells compiler not to optimize by bringing the reading of
>>>stopmachine_state out of the while loop.
>>
>>Those barriers should already prevent compiler optimalization, no? If
>>they do not, just use some barriers that do.


I hit the problem when compiling 2.6 kernel by intel compiler.
How about to change the type of stopmachine_state to atomic_t?

^ permalink raw reply	[flat|nested] 13+ messages in thread
* RE: [BUG] Variable stopmachine_state should be volatile
@ 2005-12-01  2:58 Zhang, Yanmin
  2005-12-01  3:25 ` Pavel Machek
  0 siblings, 1 reply; 13+ messages in thread
From: Zhang, Yanmin @ 2005-12-01  2:58 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel, Pallipadi, Venkatesh, Shah, Rajesh

>>-----Original Message-----
>>From: Pavel Machek [mailto:pavel@ucw.cz]
>>Sent: 2005年12月1日 6:20
>>To: Zhang, Yanmin
>>Cc: linux-kernel@vger.kernel.org; Pallipadi, Venkatesh; Shah, Rajesh
>>Subject: Re: [BUG] Variable stopmachine_state should be volatile
>>
>>Hi!
>>
>>> The model to access variable stopmachine_state is that a main thread
>>> writes it and other threads read it. Its declaration has no sign
>>> volatile. In the while loop in function stopmachine, this variable is
>>> read, and compiler might optimize it by reading it once before the loop
>>> and not reading it again in the loop, so the thread might enter dead
>>> loop.
>>
>>No. volatile may look like a solution, but it usually is not. You may
>>need some barriers, atomic_t or locking.
>>								Pavel
The original functions already use smp_mb/smp_wmb. My patch just tells compiler not to optimize by bringing the reading of stopmachine_state out of the while loop.


^ permalink raw reply	[flat|nested] 13+ messages in thread
* [BUG] Variable stopmachine_state should be volatile
@ 2005-11-30  2:04 Zhang, Yanmin
  2005-11-30 22:19 ` Pavel Machek
  2005-12-02  8:04 ` Arjan van de Ven
  0 siblings, 2 replies; 13+ messages in thread
From: Zhang, Yanmin @ 2005-11-30  2:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: Pallipadi, Venkatesh, Shah, Rajesh

[-- Attachment #1: Type: text/plain, Size: 449 bytes --]

The model to access variable stopmachine_state is that a main thread
writes it and other threads read it. Its declaration has no sign
volatile. In the while loop in function stopmachine, this variable is
read, and compiler might optimize it by reading it once before the loop
and not reading it again in the loop, so the thread might enter dead
loop.

Here is the patch to fix it.

Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>



[-- Attachment #2: stopmachine_state_volatile_2.6.15_rc3.patch --]
[-- Type: application/octet-stream, Size: 563 bytes --]

diff -Nraup linux-2.6.15-rc3/kernel/stop_machine.c linux-2.6.15-rc3_fix/kernel/stop_machine.c
--- linux-2.6.15-rc3/kernel/stop_machine.c	2005-11-29 00:02:44.000000000 +0800
+++ linux-2.6.15-rc3_fix/kernel/stop_machine.c	2005-11-29 00:03:47.000000000 +0800
@@ -20,7 +20,7 @@ enum stopmachine_state {
 	STOPMACHINE_EXIT,
 };
 
-static enum stopmachine_state stopmachine_state;
+static volatile enum stopmachine_state stopmachine_state;
 static unsigned int stopmachine_num_threads;
 static atomic_t stopmachine_thread_ack;
 static DECLARE_MUTEX(stopmachine_mutex);

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2005-12-12 13:39 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-12-08  1:37 [BUG] Variable stopmachine_state should be volatile Zhang, Yanmin
2005-12-12 13:39 ` Christoph Hellwig
  -- strict thread matches above, loose matches on Subject: below --
2005-12-12  7:06 Zhang, Yanmin
2005-12-08 18:53 Luck, Tony
     [not found] <88056F38E9E48644A0F562A38C64FB60067BE61C@scsmsx403.amr.corp.intel.com>
2005-12-02  3:53 ` Pavel Machek
2005-12-02  2:48 Zhang, Yanmin
2005-12-01  5:27 Zhang, Yanmin
2005-12-01 10:26 ` Pavel Machek
2005-12-01  2:58 Zhang, Yanmin
2005-12-01  3:25 ` Pavel Machek
2005-11-30  2:04 Zhang, Yanmin
2005-11-30 22:19 ` Pavel Machek
2005-12-02  8:04 ` Arjan van de Ven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox