linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ia64: disable preemption in udelay()
@ 2005-12-14 23:25 hawkes
  2005-12-15 22:50 ` Luck, Tony
  0 siblings, 1 reply; 18+ messages in thread
From: hawkes @ 2005-12-14 23:25 UTC (permalink / raw)
  To: Tony Luck, Andrew Morton, linux-ia64, linux-kernel
  Cc: Jack Steiner, Keith Owens, hawkes, Dimitri Sivanich

Sending this to a wider audience:

The udelay() inline for ia64 uses the ITC.  If CONFIG_PREEMPT is enabled
and the platform has unsynchronized ITCs and the calling task migrates
to another CPU while doing the udelay loop, then the effective delay may
be too short or very, very long.

The most simple fix is to disable preemption around the udelay looping.
The downside is that this inhibits realtime preemption for cases of long
udelays.  One datapoint:  an SGI realtime engineer reports that if
CONFIG_PREEMPT is turned off, that no significant holdoffs are
are attributed to udelay().

I am reluctant to propose a much more complicated patch (that disables
preemption only for "short" delays, and uses the global RTC as the time
base for longer, preemptible delays) unless this patch introduces
significant and unacceptable preemption delays.

Signed-off-by: John Hawkes <hawkes@sgi.com>

Index: linux/include/asm-ia64/delay.h
===================================================================
--- linux.orig/include/asm-ia64/delay.h	2005-10-27 17:02:08.000000000 -0700
+++ linux/include/asm-ia64/delay.h	2005-12-14 10:30:55.000000000 -0800
@@ -87,11 +87,17 @@
 static __inline__ void
 udelay (unsigned long usecs)
 {
-	unsigned long start = ia64_get_itc();
-	unsigned long cycles = usecs*local_cpu_data->cyc_per_usec;
+	unsigned long start;
+	unsigned long cycles;
+
+	preempt_disable();
+	cycles = usecs*local_cpu_data->cyc_per_usec;
+	start = ia64_get_itc();
 
 	while (ia64_get_itc() - start < cycles)
 		cpu_relax();
+
+	preempt_enable();
 }
 
 #endif /* _ASM_IA64_DELAY_H */

^ permalink raw reply	[flat|nested] 18+ messages in thread
* Re: [PATCH] ia64: disable preemption in udelay()
@ 2005-12-16  2:42 hawkes
  2005-12-16 12:28 ` Robin Holt
  0 siblings, 1 reply; 18+ messages in thread
From: hawkes @ 2005-12-16  2:42 UTC (permalink / raw)
  To: Tony Luck, Andrew Morton, linux-ia64, linux-kernel
  Cc: Jack Steiner, Keith Owens, hawkes, Dimitri Sivanich

Resubmitting using Tony Luck's suggested alternative.

The udelay() inline for ia64 uses the ITC.  If CONFIG_PREEMPT is enabled
and the platform has unsynchronized ITCs and the calling task migrates
to another CPU while doing the udelay loop, then the effective delay may
be too short or very, very long.

This patch disables preemption around 100 usec chunks of the overall
desired udelay time.  This minimizes preemption-holdoffs.

Signed-off-by: John Hawkes <hawkes@sgi.com>

Index: linux/include/asm-ia64/delay.h
===================================================================
--- linux.orig/include/asm-ia64/delay.h	2005-12-15 15:34:16.000000000 -0800
+++ linux/include/asm-ia64/delay.h	2005-12-15 15:34:57.000000000 -0800
@@ -84,14 +84,6 @@
 	ia64_delay_loop (loops - 1);
 }
 
-static __inline__ void
-udelay (unsigned long usecs)
-{
-	unsigned long start = ia64_get_itc();
-	unsigned long cycles = usecs*local_cpu_data->cyc_per_usec;
-
-	while (ia64_get_itc() - start < cycles)
-		cpu_relax();
-}
+extern void udelay (unsigned long usecs);
 
 #endif /* _ASM_IA64_DELAY_H */
Index: linux/arch/ia64/kernel/time.c
===================================================================
--- linux.orig/arch/ia64/kernel/time.c	2005-12-15 15:34:16.000000000 -0800
+++ linux/arch/ia64/kernel/time.c	2005-12-15 15:34:57.000000000 -0800
@@ -249,3 +249,31 @@
 	 */
 	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
 }
+
+#define SMALLUSECS 100
+
+void
+udelay (unsigned long usecs)
+{
+	unsigned long start;
+	unsigned long cycles;
+	unsigned long smallusecs;
+
+	/*
+	 * Execute the non-preemptible delay loop (because the ITC might
+	 * not be synchronized between CPUS) in relatively short time
+	 * chunks, allowing preemption between the chunks.
+	 */
+	while (usecs > 0) {
+		smallusecs = (usecs > SMALLUSECS) ? SMALLUSECS : usecs;
+		preempt_disable();
+		cycles = smallusecs*local_cpu_data->cyc_per_usec;
+		start = ia64_get_itc();
+
+		while (ia64_get_itc() - start < cycles)
+			cpu_relax();
+
+		preempt_enable();
+		usecs -= smallusecs;
+	}
+}

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

end of thread, other threads:[~2005-12-23  5:58 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-12-14 23:25 [PATCH] ia64: disable preemption in udelay() hawkes
2005-12-15 22:50 ` Luck, Tony
2005-12-16  1:04   ` Luck, Tony
2005-12-16  8:20     ` Christian Hildner
2005-12-16 14:14     ` Alan Cox
2005-12-16  1:52   ` Zwane Mwaikambo
2005-12-16  2:03     ` Lee Revell
2005-12-16  2:12       ` John Hawkes
2005-12-16  2:40         ` Zwane Mwaikambo
2005-12-16  3:19         ` Lee Revell
2005-12-22 21:45           ` Bill Davidsen
2005-12-23  0:14             ` Keith Owens
2005-12-23  6:03               ` Zwane Mwaikambo
2005-12-16  2:37       ` Zwane Mwaikambo
2005-12-16  2:42 hawkes
2005-12-16 12:28 ` Robin Holt
2005-12-16 17:33   ` Luck, Tony
2005-12-16 18:39     ` John Hawkes

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).