[patch] "big IRQ lock" removal, 2.5.27-A7

From: Ingo Molnar (mingo@elte.hu)
Date: Sun Jul 21 2002 - 15:59:46 EST


the arch/i386/kernel/vm86.c hacks are fixed now as well:

      http://redhat.com/~mingo/remove-irqlock-patches/remove-irqlock-2.5.27-A7

this was relatively simple, the irqbits global variable needed to be
protected by a global spinlock. I found no other global locking assumption
in the code. In fact there was even a small bug in the code - if
free_vm86_irq() was called outside of the global IRQ lock then there's a
irqbits corruption window in free_vm87_irq() - this is true even though
that particular IRQ source will not interfere - it's other IRQ sources
that might change the irqbits variable. The patch fixes this.

this was the last remaining x86 usage of cli()/sti().

        Ingo

--- linux/arch/i386/kernel/vm86.c.orig Sun Jun 9 07:27:22 2002
+++ linux/arch/i386/kernel/vm86.c Sun Jul 21 22:55:57 2002
@@ -571,6 +571,8 @@
         struct task_struct *tsk;
         int sig;
 } vm86_irqs[16];
+
+static spinlock_t irqbits_lock = SPIN_LOCK_UNLOCKED;
 static int irqbits;
 
 #define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \
@@ -580,9 +582,8 @@
 static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
         int irq_bit;
         unsigned long flags;
-
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(&irqbits_lock, flags);
         irq_bit = 1 << intno;
         if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
                 goto out;
@@ -591,14 +592,19 @@
                 send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
         /* else user will poll for IRQs */
 out:
- restore_flags(flags);
+ spin_unlock_irqrestore(&irqbits_lock, flags);
 }
 
 static inline void free_vm86_irq(int irqnumber)
 {
+ unsigned long flags;
+
         free_irq(irqnumber,0);
         vm86_irqs[irqnumber].tsk = 0;
+
+ spin_lock_irqsave(&irqbits_lock, flags);
         irqbits &= ~(1 << irqnumber);
+ spin_unlock_irqrestore(&irqbits_lock, flags);
 }
 
 static inline int task_valid(struct task_struct *tsk)
@@ -635,11 +641,10 @@
         
         if ( (irqnumber<3) || (irqnumber>15) ) return 0;
         if (vm86_irqs[irqnumber].tsk != current) return 0;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&irqbits_lock, flags);
         bit = irqbits & (1 << irqnumber);
         irqbits &= ~bit;
- restore_flags(flags);
+ spin_unlock_irqrestore(&irqbits_lock, flags);
         return bit;
 }
 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Jul 23 2002 - 22:00:36 EST