Re: Possible race condition in i386 global_irq_lock handling.

From: TeJun Huh
Date: Thu Aug 21 2003 - 20:18:00 EST


I'm attaching patch for i386. It makes three changes.

1. add smp_mb() between local_irq_count++ and global_irq_lock test
in irq_enter().
2. add smp_mb__after_clear_bit() before irqs_running() test in
wait_on_irq().
3. remove irqs_running() test from synchronize_irq()

Removing irqs_running() test from synchronize_irq() is needed for the
same reason. Other interrupts might be running on successful return
from synchronize_irq().

smp_mb__after_clear_bit() should be smp_mb__after_test_and_set_bit()
which doesn't exist. Should I add this?

After determining smp_mb__after_clear_bit(), I'll make a patch for
every affected architecture. Please comment.

# ------------ patch follows --------------

diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c Fri Aug 22 10:07:50 2003
+++ b/arch/i386/kernel/irq.c Fri Aug 22 10:07:50 2003
@@ -271,6 +271,8 @@
* for bottom half handlers unless we're
* already executing in one..
*/
+ smp_mb__after_clear_bit(); /* Synchronize with irq_enter() */
+
if (!irqs_running())
if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
break;
@@ -307,11 +309,9 @@
*/
void synchronize_irq(void)
{
- if (irqs_running()) {
- /* Stupid approach */
- cli();
- sti();
- }
+ /* Stupid approach */
+ cli();
+ sti();
}

static inline void get_irqlock(int cpu)
diff -Nru a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
--- a/include/asm-i386/hardirq.h Fri Aug 22 10:07:50 2003
+++ b/include/asm-i386/hardirq.h Fri Aug 22 10:07:50 2003
@@ -67,6 +67,8 @@
{
++local_irq_count(cpu);

+ smp_mb(); /* Synchronize with wait_on_irq() */
+
while (test_bit(0,&global_irq_lock)) {
cpu_relax();
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/