Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IA64] disable preemption in udelay()

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.

udelay() is now too big to be inline, move it out of line and export it.

Signed-off-by: John Hawkes <hawkes@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

John Hawkes and committed by
Tony Luck
f5899b5d 7b666653

+30 -9
+29
arch/ia64/kernel/time.c
··· 249 249 */ 250 250 set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); 251 251 } 252 + 253 + #define SMALLUSECS 100 254 + 255 + void 256 + udelay (unsigned long usecs) 257 + { 258 + unsigned long start; 259 + unsigned long cycles; 260 + unsigned long smallusecs; 261 + 262 + /* 263 + * Execute the non-preemptible delay loop (because the ITC might 264 + * not be synchronized between CPUS) in relatively short time 265 + * chunks, allowing preemption between the chunks. 266 + */ 267 + while (usecs > 0) { 268 + smallusecs = (usecs > SMALLUSECS) ? SMALLUSECS : usecs; 269 + preempt_disable(); 270 + cycles = smallusecs*local_cpu_data->cyc_per_usec; 271 + start = ia64_get_itc(); 272 + 273 + while (ia64_get_itc() - start < cycles) 274 + cpu_relax(); 275 + 276 + preempt_enable(); 277 + usecs -= smallusecs; 278 + } 279 + } 280 + EXPORT_SYMBOL(udelay);
+1 -9
include/asm-ia64/delay.h
··· 84 84 ia64_delay_loop (loops - 1); 85 85 } 86 86 87 - static __inline__ void 88 - udelay (unsigned long usecs) 89 - { 90 - unsigned long start = ia64_get_itc(); 91 - unsigned long cycles = usecs*local_cpu_data->cyc_per_usec; 92 - 93 - while (ia64_get_itc() - start < cycles) 94 - cpu_relax(); 95 - } 87 + extern void udelay (unsigned long usecs); 96 88 97 89 #endif /* _ASM_IA64_DELAY_H */