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