From: Anton Blanchard <anton@samba.org>

Also add cpu_relax() to several spinloops in xmon which wait for other cpus.


---

 arch/ppc64/xmon/xmon.c     |   14 +++++++++-----
 drivers/char/hvc_console.c |    9 +++++----
 2 files changed, 14 insertions(+), 9 deletions(-)

diff -puN arch/ppc64/xmon/xmon.c~ppc64-xmon-cpumask arch/ppc64/xmon/xmon.c
--- 25/arch/ppc64/xmon/xmon.c~ppc64-xmon-cpumask	2004-02-04 02:24:54.000000000 -0800
+++ 25-akpm/arch/ppc64/xmon/xmon.c	2004-02-04 02:24:54.000000000 -0800
@@ -16,6 +16,7 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/kallsyms.h>
+#include <linux/cpumask.h>
 
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -37,7 +38,7 @@
 #define skipbl	xmon_skipbl
 
 #ifdef CONFIG_SMP
-volatile unsigned long cpus_in_xmon = 0;
+volatile cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 static unsigned long got_xmon = 0;
 static volatile int take_xmon = -1;
 static volatile int leaving_xmon = 0;
@@ -288,17 +289,18 @@ xmon(struct pt_regs *excp)
 	leaving_xmon = 0;
 	/* possible race condition here if a CPU is held up and gets
 	 * here while we are exiting */
-	if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) {
+	if (cpu_test_and_set(smp_processor_id(), cpus_in_xmon)) {
 		/* xmon probably caused an exception itself */
 		printf("We are already in xmon\n");
 		for (;;)
-			;
+			cpu_relax();
 	}
 	while (test_and_set_bit(0, &got_xmon)) {
 		if (take_xmon == smp_processor_id()) {
 			take_xmon = -1;
 			break;
 		}
+		cpu_relax();
 	}
 	/*
 	 * XXX: breakpoints are removed while any cpu is in xmon
@@ -325,7 +327,7 @@ xmon(struct pt_regs *excp)
 	leaving_xmon = 1;
 	if (cmd != 's')
 		clear_bit(0, &got_xmon);
-	clear_bit(smp_processor_id(), &cpus_in_xmon);
+	cpu_clear(smp_processor_id(), cpus_in_xmon);
 #endif /* CONFIG_SMP */
 	set_msrd(msr);		/* restore interrupt enable */
 }
@@ -602,6 +604,7 @@ cmds(struct pt_regs *excp)
 			printf(" (type ? for help)\n");
 			break;
 		}
+		cpu_relax();
 	}
 }
 
@@ -638,7 +641,7 @@ static void cpu_cmd(void)
 		/* print cpus waiting or in xmon */
 		printf("cpus stopped:");
 		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-			if (test_bit(cpu, &cpus_in_xmon)) {
+			if (cpu_isset(cpu, cpus_in_xmon)) {
 				printf(" %x", cpu);
 				if (cpu == smp_processor_id())
 					printf("*", cpu);
@@ -664,6 +667,7 @@ static void cpu_cmd(void)
 			take_xmon = -1;
 			break;
 		}
+		cpu_relax();
 	}
 }
 #endif /* CONFIG_SMP */
diff -puN drivers/char/hvc_console.c~ppc64-xmon-cpumask drivers/char/hvc_console.c
--- 25/drivers/char/hvc_console.c~ppc64-xmon-cpumask	2004-02-04 02:24:54.000000000 -0800
+++ 25-akpm/drivers/char/hvc_console.c	2004-02-04 02:24:54.000000000 -0800
@@ -29,6 +29,7 @@
 #include <linux/kbd_kern.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
+#include <linux/cpumask.h>
 
 extern int hvc_count(int *);
 extern int hvc_get_chars(int index, char *buf, int count);
@@ -223,10 +224,10 @@ static void hvc_poll(int index)
 	spin_unlock_irqrestore(&hp->lock, flags);
 }
 
-#if defined (CONFIG_XMON)
-extern unsigned long cpus_in_xmon;
+#if defined(CONFIG_XMON) && defined(CONFIG_SMP)
+extern cpumask_t cpus_in_xmon;
 #else
-unsigned long cpus_in_xmon=0;
+static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 #endif
 
 
@@ -237,7 +238,7 @@ int khvcd(void *unused)
 	daemonize("khvcd");
 
 	for (;;) {
-		if (!cpus_in_xmon) {
+		if (cpus_empty(cpus_in_xmon)) {
 			for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i)
 				hvc_poll(i);
 		}

_