Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5899b5d authored by John Hawkes's avatar John Hawkes Committed by Tony Luck
Browse files

[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: default avatarJohn Hawkes <hawkes@sgi.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 7b666653
Loading
Loading
Loading
Loading
+29 −0
Original line number Original line Diff line number Diff line
@@ -249,3 +249,32 @@ time_init (void)
	 */
	 */
	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
	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;
	}
}
EXPORT_SYMBOL(udelay);
+1 −9
Original line number Original line Diff line number Diff line
@@ -84,14 +84,6 @@ __delay (unsigned long loops)
	ia64_delay_loop (loops - 1);
	ia64_delay_loop (loops - 1);
}
}


static __inline__ void
extern void udelay (unsigned long usecs);
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();
}


#endif /* _ASM_IA64_DELAY_H */
#endif /* _ASM_IA64_DELAY_H */