Quick fix for bitrot in locking in the SMP case. cd_getreg() and

cd_setreg() were still using !(read_eflags() & PSL_I) as the condition
for the lock hidden by COM_LOCK() (if any) being held.  This worked
when spin mutexes and/or critical_enter() used hard interrupt disablement,
but it has caused recursion on the non-recursive mutex com_mtx since
all relevant interrupt disablement became soft.  The recursion is
harmless unless there are other bugs, but it breaks an invariant so
it is fatal if spinlocks are witnessed.
This commit is contained in:
bde 2003-09-27 10:30:03 +00:00
parent 573654b93e
commit 6d69006c55
3 changed files with 72 additions and 12 deletions

View File

@ -2852,6 +2852,9 @@ cd_getreg(com, reg)
int cy_align;
register_t eflags;
cy_addr iobase;
#ifdef SMP
int need_unlock;
#endif
int val;
basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
@ -2860,13 +2863,20 @@ cd_getreg(com, reg)
iobase = com->iobase;
eflags = read_eflags();
critical_enter();
if (eflags & PSL_I)
#ifdef SMP
need_unlock = 0;
if (!mtx_owned(&com_mtx)) {
COM_LOCK();
need_unlock = 1;
}
#endif
if (basecom->car != car)
cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
val = cd_inb(iobase, reg, cy_align);
if (eflags & PSL_I)
#ifdef SMP
if (need_unlock)
COM_UNLOCK();
#endif
critical_exit();
return (val);
}
@ -2882,6 +2892,9 @@ cd_setreg(com, reg, val)
int cy_align;
register_t eflags;
cy_addr iobase;
#ifdef SMP
int need_unlock;
#endif
basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
car = com->unit & CD1400_CAR_CHAN;
@ -2889,13 +2902,20 @@ cd_setreg(com, reg, val)
iobase = com->iobase;
eflags = read_eflags();
critical_enter();
if (eflags & PSL_I)
#ifdef SMP
need_unlock = 0;
if (!mtx_owned(&com_mtx)) {
COM_LOCK();
need_unlock = 1;
}
#endif
if (basecom->car != car)
cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
cd_outb(iobase, reg, cy_align, val);
if (eflags & PSL_I)
#ifdef SMP
if (need_unlock)
COM_UNLOCK();
#endif
critical_exit();
}

View File

@ -2852,6 +2852,9 @@ cd_getreg(com, reg)
int cy_align;
register_t eflags;
cy_addr iobase;
#ifdef SMP
int need_unlock;
#endif
int val;
basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
@ -2860,13 +2863,20 @@ cd_getreg(com, reg)
iobase = com->iobase;
eflags = read_eflags();
critical_enter();
if (eflags & PSL_I)
#ifdef SMP
need_unlock = 0;
if (!mtx_owned(&com_mtx)) {
COM_LOCK();
need_unlock = 1;
}
#endif
if (basecom->car != car)
cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
val = cd_inb(iobase, reg, cy_align);
if (eflags & PSL_I)
#ifdef SMP
if (need_unlock)
COM_UNLOCK();
#endif
critical_exit();
return (val);
}
@ -2882,6 +2892,9 @@ cd_setreg(com, reg, val)
int cy_align;
register_t eflags;
cy_addr iobase;
#ifdef SMP
int need_unlock;
#endif
basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
car = com->unit & CD1400_CAR_CHAN;
@ -2889,13 +2902,20 @@ cd_setreg(com, reg, val)
iobase = com->iobase;
eflags = read_eflags();
critical_enter();
if (eflags & PSL_I)
#ifdef SMP
need_unlock = 0;
if (!mtx_owned(&com_mtx)) {
COM_LOCK();
need_unlock = 1;
}
#endif
if (basecom->car != car)
cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
cd_outb(iobase, reg, cy_align, val);
if (eflags & PSL_I)
#ifdef SMP
if (need_unlock)
COM_UNLOCK();
#endif
critical_exit();
}

View File

@ -2852,6 +2852,9 @@ cd_getreg(com, reg)
int cy_align;
register_t eflags;
cy_addr iobase;
#ifdef SMP
int need_unlock;
#endif
int val;
basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
@ -2860,13 +2863,20 @@ cd_getreg(com, reg)
iobase = com->iobase;
eflags = read_eflags();
critical_enter();
if (eflags & PSL_I)
#ifdef SMP
need_unlock = 0;
if (!mtx_owned(&com_mtx)) {
COM_LOCK();
need_unlock = 1;
}
#endif
if (basecom->car != car)
cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
val = cd_inb(iobase, reg, cy_align);
if (eflags & PSL_I)
#ifdef SMP
if (need_unlock)
COM_UNLOCK();
#endif
critical_exit();
return (val);
}
@ -2882,6 +2892,9 @@ cd_setreg(com, reg, val)
int cy_align;
register_t eflags;
cy_addr iobase;
#ifdef SMP
int need_unlock;
#endif
basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
car = com->unit & CD1400_CAR_CHAN;
@ -2889,13 +2902,20 @@ cd_setreg(com, reg, val)
iobase = com->iobase;
eflags = read_eflags();
critical_enter();
if (eflags & PSL_I)
#ifdef SMP
need_unlock = 0;
if (!mtx_owned(&com_mtx)) {
COM_LOCK();
need_unlock = 1;
}
#endif
if (basecom->car != car)
cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
cd_outb(iobase, reg, cy_align, val);
if (eflags & PSL_I)
#ifdef SMP
if (need_unlock)
COM_UNLOCK();
#endif
critical_exit();
}