Change simple lock handling to not depend upon having a local apic

available.  The per-cpu variable ss_tpr has been replaced by ss_eflags.
This reduced the number of interrupts sent to the wrong CPU, due to
the cpu having the global lock being inside a critical region.

Remove some unneeded manipulation of tpr register in mplock.s.

Adjust code in mplock.s to be aware of variables on the stack being
destroyed by MPgetlock if GRAB_LOPRIO is defined.
This commit is contained in:
Tor Egge
1998-05-17 23:08:04 +00:00
parent 333c76c66d
commit 5d183e9691
8 changed files with 55 additions and 51 deletions
+2 -2
View File
@@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
* $Id: genassym.c,v 1.55 1998/05/17 18:53:11 tegge Exp $ * $Id: genassym.c,v 1.56 1998/05/17 22:12:07 tegge Exp $
*/ */
#include "opt_vm86.h" #include "opt_vm86.h"
@@ -218,7 +218,7 @@ main()
printf("#define\tGD_CPU_LOCKID %d\n", &globaldata->cpu_lockid); printf("#define\tGD_CPU_LOCKID %d\n", &globaldata->cpu_lockid);
printf("#define\tGD_OTHER_CPUS %d\n", &globaldata->other_cpus); printf("#define\tGD_OTHER_CPUS %d\n", &globaldata->other_cpus);
printf("#define\tGD_MY_IDLEPTD %d\n", &globaldata->my_idlePTD); printf("#define\tGD_MY_IDLEPTD %d\n", &globaldata->my_idlePTD);
printf("#define\tGD_SS_TPR %d\n", &globaldata->ss_tpr); printf("#define\tGD_SS_EFLAGS %d\n", &globaldata->ss_eflags);
printf("#define\tGD_PRV_CMAP1 %d\n", &globaldata->prv_CMAP1); printf("#define\tGD_PRV_CMAP1 %d\n", &globaldata->prv_CMAP1);
printf("#define\tGD_PRV_CMAP2 %d\n", &globaldata->prv_CMAP2); printf("#define\tGD_PRV_CMAP2 %d\n", &globaldata->prv_CMAP2);
printf("#define\tGD_PRV_CMAP3 %d\n", &globaldata->prv_CMAP3); printf("#define\tGD_PRV_CMAP3 %d\n", &globaldata->prv_CMAP3);
+2 -2
View File
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: globaldata.h,v 1.2 1998/04/06 18:59:15 peter Exp $ * $Id: globaldata.h,v 1.3 1998/05/17 18:53:07 tegge Exp $
*/ */
/* /*
@@ -53,7 +53,7 @@ struct globaldata {
u_int cpu_lockid; u_int cpu_lockid;
u_int other_cpus; u_int other_cpus;
pd_entry_t *my_idlePTD; pd_entry_t *my_idlePTD;
u_int ss_tpr; u_int ss_eflags;
pt_entry_t *prv_CMAP1; pt_entry_t *prv_CMAP1;
pt_entry_t *prv_CMAP2; pt_entry_t *prv_CMAP2;
pt_entry_t *prv_CMAP3; pt_entry_t *prv_CMAP3;
+2 -2
View File
@@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
* $Id: genassym.c,v 1.55 1998/05/17 18:53:11 tegge Exp $ * $Id: genassym.c,v 1.56 1998/05/17 22:12:07 tegge Exp $
*/ */
#include "opt_vm86.h" #include "opt_vm86.h"
@@ -218,7 +218,7 @@ main()
printf("#define\tGD_CPU_LOCKID %d\n", &globaldata->cpu_lockid); printf("#define\tGD_CPU_LOCKID %d\n", &globaldata->cpu_lockid);
printf("#define\tGD_OTHER_CPUS %d\n", &globaldata->other_cpus); printf("#define\tGD_OTHER_CPUS %d\n", &globaldata->other_cpus);
printf("#define\tGD_MY_IDLEPTD %d\n", &globaldata->my_idlePTD); printf("#define\tGD_MY_IDLEPTD %d\n", &globaldata->my_idlePTD);
printf("#define\tGD_SS_TPR %d\n", &globaldata->ss_tpr); printf("#define\tGD_SS_EFLAGS %d\n", &globaldata->ss_eflags);
printf("#define\tGD_PRV_CMAP1 %d\n", &globaldata->prv_CMAP1); printf("#define\tGD_PRV_CMAP1 %d\n", &globaldata->prv_CMAP1);
printf("#define\tGD_PRV_CMAP2 %d\n", &globaldata->prv_CMAP2); printf("#define\tGD_PRV_CMAP2 %d\n", &globaldata->prv_CMAP2);
printf("#define\tGD_PRV_CMAP3 %d\n", &globaldata->prv_CMAP3); printf("#define\tGD_PRV_CMAP3 %d\n", &globaldata->prv_CMAP3);
+3 -3
View File
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: globals.s,v 1.2 1998/04/06 18:59:14 peter Exp $ * $Id: globals.s,v 1.3 1998/05/17 18:53:19 tegge Exp $
*/ */
#include "opt_vm86.h" #include "opt_vm86.h"
@@ -86,7 +86,7 @@ globaldata:
* The BSP version of these get setup in locore.s and pmap.c, while * The BSP version of these get setup in locore.s and pmap.c, while
* the AP versions are setup in mp_machdep.c. * the AP versions are setup in mp_machdep.c.
*/ */
.globl _cpuid,_cpu_lockid,_other_cpus,_my_idlePTD,_ss_tpr .globl _cpuid,_cpu_lockid,_other_cpus,_my_idlePTD,_ss_eflags
.globl _prv_CMAP1,_prv_CMAP2,_prv_CMAP3,_prv_PMAP1 .globl _prv_CMAP1,_prv_CMAP2,_prv_CMAP3,_prv_PMAP1
.globl _inside_intr .globl _inside_intr
@@ -94,7 +94,7 @@ globaldata:
.set _cpu_lockid,globaldata + GD_CPU_LOCKID .set _cpu_lockid,globaldata + GD_CPU_LOCKID
.set _other_cpus,globaldata + GD_OTHER_CPUS .set _other_cpus,globaldata + GD_OTHER_CPUS
.set _my_idlePTD,globaldata + GD_MY_IDLEPTD .set _my_idlePTD,globaldata + GD_MY_IDLEPTD
.set _ss_tpr,globaldata + GD_SS_TPR .set _ss_eflags,globaldata + GD_SS_EFLAGS
.set _prv_CMAP1,globaldata + GD_PRV_CMAP1 .set _prv_CMAP1,globaldata + GD_PRV_CMAP1
.set _prv_CMAP2,globaldata + GD_PRV_CMAP2 .set _prv_CMAP2,globaldata + GD_PRV_CMAP2
.set _prv_CMAP3,globaldata + GD_PRV_CMAP3 .set _prv_CMAP3,globaldata + GD_PRV_CMAP3
+22 -8
View File
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* $Id: mplock.s,v 1.22 1997/08/29 18:16:17 fsmp Exp $ * $Id: mplock.s,v 1.23 1997/08/30 08:08:10 fsmp Exp $
* *
* Functions for locking between CPUs in a SMP system. * Functions for locking between CPUs in a SMP system.
* *
@@ -77,7 +77,7 @@
/*********************************************************************** /***********************************************************************
* void MPgetlock(unsigned int *lock) * void MPgetlock(unsigned int *lock)
* ---------------------------------- * ----------------------------------
* Destroys %eax, %ecx and %edx. * Destroys %eax, %ecx, %edx and 12(%esp).
*/ */
NON_GPROF_ENTRY(MPgetlock) NON_GPROF_ENTRY(MPgetlock)
@@ -213,7 +213,6 @@ NON_GPROF_ENTRY(get_mplock)
pushfl /* save current EFLAGS */ pushfl /* save current EFLAGS */
testl $(1<<9), (%esp) /* test EI bit */ testl $(1<<9), (%esp) /* test EI bit */
jnz 1f /* INTs currently enabled */ jnz 1f /* INTs currently enabled */
movl $TPR_IGNORE_HWI, lapic_tpr /* CHEAP_TPR */
sti /* allow IPI and FAST INTs */ sti /* allow IPI and FAST INTs */
1: 1:
pushl $_mp_lock pushl $_mp_lock
@@ -238,10 +237,20 @@ NON_GPROF_ENTRY(boot_get_mplock)
pushl %ecx pushl %ecx
pushl %edx pushl %edx
#ifdef GRAB_LOPRIO
pushl $0
pushfl
#endif
pushl $_mp_lock pushl $_mp_lock
call _MPgetlock call _MPgetlock
add $4, %esp add $4, %esp
#ifdef GRAB_LOPRIO
popfl
addl $4, %esp
#endif
popl %edx popl %edx
popl %ecx popl %ecx
popl %eax popl %eax
@@ -298,7 +307,6 @@ NON_GPROF_ENTRY(get_isrlock)
/* block all HW INTs via Task Priority Register */ /* block all HW INTs via Task Priority Register */
pushl lapic_tpr /* save current TPR */ pushl lapic_tpr /* save current TPR */
pushfl /* save current EFLAGS */ pushfl /* save current EFLAGS */
movl $TPR_IGNORE_HWI, lapic_tpr /* CHEAP_TPR */
sti /* allow IPI and FAST INTs */ sti /* allow IPI and FAST INTs */
pushl $_mp_lock pushl $_mp_lock
@@ -344,7 +352,6 @@ NON_GPROF_ENTRY(rel_isrlock)
NON_GPROF_ENTRY(get_fpu_lock) NON_GPROF_ENTRY(get_fpu_lock)
pushl lapic_tpr pushl lapic_tpr
pushfl pushfl
movl $TPR_IGNORE_HWI, lapic_tpr /* CHEAP_TPR */
sti sti
pushl $_mp_lock pushl $_mp_lock
call _MPgetlock call _MPgetlock
@@ -375,7 +382,6 @@ NON_GPROF_ENTRY(rel_fpu_lock)
NON_GPROF_ENTRY(get_align_lock) NON_GPROF_ENTRY(get_align_lock)
pushl lapic_tpr pushl lapic_tpr
pushfl pushfl
movl $TPR_IGNORE_HWI, lapic_tpr /* CHEAP_TPR */
sti sti
pushl $_mp_lock pushl $_mp_lock
call _MPgetlock call _MPgetlock
@@ -406,7 +412,6 @@ NON_GPROF_ENTRY(rel_align_lock)
NON_GPROF_ENTRY(get_syscall_lock) NON_GPROF_ENTRY(get_syscall_lock)
pushl lapic_tpr pushl lapic_tpr
pushfl pushfl
movl $TPR_IGNORE_HWI, lapic_tpr /* CHEAP_TPR */
sti sti
pushl $_mp_lock pushl $_mp_lock
call _MPgetlock call _MPgetlock
@@ -437,7 +442,6 @@ NON_GPROF_ENTRY(rel_syscall_lock)
NON_GPROF_ENTRY(get_altsyscall_lock) NON_GPROF_ENTRY(get_altsyscall_lock)
pushl lapic_tpr pushl lapic_tpr
pushfl pushfl
movl $TPR_IGNORE_HWI, lapic_tpr /* CHEAP_TPR */
sti sti
pushl $_mp_lock pushl $_mp_lock
call _MPgetlock call _MPgetlock
@@ -473,10 +477,20 @@ NON_GPROF_ENTRY(get_mpintrlock)
pushl %ecx pushl %ecx
pushl %edx pushl %edx
#ifdef GRAB_LOPRIO
pushl lapic_tpr
pushfl
#endif
pushl $_mpintr_lock pushl $_mpintr_lock
call _MPgetlock call _MPgetlock
add $4, %esp add $4, %esp
#ifdef GRAB_LOPRIO
popfl
popl lapic_tpr
#endif
popl %edx popl %edx
popl %ecx popl %ecx
popl %eax popl %eax
+20 -30
View File
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: simplelock.s,v 1.7 1997/12/15 02:18:22 tegge Exp $ * $Id: simplelock.s,v 1.8 1998/01/19 17:33:08 tegge Exp $
*/ */
/* /*
@@ -31,6 +31,7 @@
#include <machine/asmacros.h> /* miscellaneous macros */ #include <machine/asmacros.h> /* miscellaneous macros */
#include <i386/isa/intr_machdep.h> #include <i386/isa/intr_machdep.h>
#include <machine/psl.h>
#include <machine/smptests.h> /** FAST_HI */ #include <machine/smptests.h> /** FAST_HI */
@@ -102,9 +103,6 @@ gotit:
#else /* SL_DEBUG */ #else /* SL_DEBUG */
ENTRY(s_lock) ENTRY(s_lock)
cmpl $0, _smp_active
je gotit
movl 4(%esp), %edx /* get the address of the lock */ movl 4(%esp), %edx /* get the address of the lock */
setlock: setlock:
movl _cpu_lockid, %ecx /* add cpu id portion */ movl _cpu_lockid, %ecx /* add cpu id portion */
@@ -190,16 +188,17 @@ ENTRY(test_and_set)
/* /*
* These versions of simple_lock block hardware INTS, * These versions of simple_lock block interrupts,
* making it suitable for regions accessed by both top and bottom levels. * making it suitable for regions accessed by both top and bottom levels.
* This is done by saving the current value of the TPR in a per-cpu global, * This is done by saving the current value of the cpu flags in a per-cpu
* then taking the lock. On the way out the lock is released, then the * global, and disabling interrupts when the lock is taken. When the
* original value of the TPR is restored. * lock is released, interrupts might be enabled, depending upon the saved
* cpu flags.
* Because of this, it must ONLY be used for SHORT, deterministic paths! * Because of this, it must ONLY be used for SHORT, deterministic paths!
* *
* Note: * Note:
* It would appear to be "bad behaviour" to blindly store a value in * It would appear to be "bad behaviour" to blindly store a value in
* ss_tpr, as this could destroy the previous contents. But since ss_tpr * ss_eflags, as this could destroy the previous contents. But since ss_eflags
* is a per-cpu variable, and its fatal to attempt to acquire a simplelock * is a per-cpu variable, and its fatal to attempt to acquire a simplelock
* that you already hold, we get away with it. This needs to be cleaned * that you already hold, we get away with it. This needs to be cleaned
* up someday... * up someday...
@@ -214,40 +213,29 @@ ENTRY(ss_lock)
movl 4(%esp), %eax /* get the address of the lock */ movl 4(%esp), %eax /* get the address of the lock */
movl $1, %ecx /* value for a held lock */ movl $1, %ecx /* value for a held lock */
ssetlock: ssetlock:
pushl lapic_tpr /* save current task priority */ pushfl
#ifdef FAST_HI cli
movl $TPR_BLOCK_FHWI, lapic_tpr /* block FAST hw INTs */
#else
movl $TPR_BLOCK_HWI, lapic_tpr /* block hw INTs */
#endif
xchgl %ecx, (%eax) /* compete */ xchgl %ecx, (%eax) /* compete */
testl %ecx, %ecx testl %ecx, %ecx
jz sgotit /* it was clear, return */ jz sgotit /* it was clear, return */
popl lapic_tpr /* previous value while waiting */ popfl /* previous value while waiting */
swait: swait:
cmpl $0, (%eax) /* wait to empty */ cmpl $0, (%eax) /* wait to empty */
jne swait /* still set... */ jne swait /* still set... */
jmp ssetlock /* empty again, try once more */ jmp ssetlock /* empty again, try once more */
sgotit: sgotit:
popl _ss_tpr /* save the old task priority */ popl _ss_eflags /* save the old eflags */
ret ret
#else /* SL_DEBUG */ #else /* SL_DEBUG */
ENTRY(ss_lock) ENTRY(ss_lock)
cmpl $0, _smp_active
je sgotit2
movl 4(%esp), %edx /* get the address of the lock */ movl 4(%esp), %edx /* get the address of the lock */
ssetlock: ssetlock:
movl _cpu_lockid, %ecx /* add cpu id portion */ movl _cpu_lockid, %ecx /* add cpu id portion */
incl %ecx /* add lock portion */ incl %ecx /* add lock portion */
pushl lapic_tpr /* save current task priority */ pushfl
#ifdef FAST_HI cli
movl $TPR_BLOCK_FHWI, lapic_tpr /* block FAST hw INTs */
#else
movl $TPR_BLOCK_HWI, lapic_tpr /* block hw INTs */
#endif
movl $0, %eax movl $0, %eax
lock lock
cmpxchgl %ecx, (%edx) /* compete */ cmpxchgl %ecx, (%edx) /* compete */
@@ -257,13 +245,13 @@ ssetlock:
cmpl _cpu_lockid, %eax /* do we hold it? */ cmpl _cpu_lockid, %eax /* do we hold it? */
je sbad_slock /* yes, thats not good... */ je sbad_slock /* yes, thats not good... */
addl $4, %esp /* clear the stack */ addl $4, %esp /* clear the stack */
popl lapic_tpr /* previous value while waiting */ popfl
swait: swait:
cmpl $0, (%edx) /* wait to empty */ cmpl $0, (%edx) /* wait to empty */
jne swait /* still set... */ jne swait /* still set... */
jmp ssetlock /* empty again, try once more */ jmp ssetlock /* empty again, try once more */
sgotit: sgotit:
popl _ss_tpr /* save the old task priority */ popl _ss_eflags /* save the old task priority */
sgotit2: sgotit2:
ret ret
@@ -285,8 +273,10 @@ sbsl1: .asciz "rsslock: cpu: %d, addr: 0x%08x, lock: 0x%08x"
ENTRY(ss_unlock) ENTRY(ss_unlock)
movl 4(%esp), %eax /* get the address of the lock */ movl 4(%esp), %eax /* get the address of the lock */
movl $0, (%eax) /* clear the simple lock */ movl $0, (%eax) /* clear the simple lock */
movl _ss_tpr, %eax testl $PSL_I, _ss_eflags
movl %eax, lapic_tpr /* restore the old task priority */ jz ss_unlock2
sti
ss_unlock2:
ret ret
/* /*
+2 -2
View File
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: globaldata.h,v 1.2 1998/04/06 18:59:15 peter Exp $ * $Id: globaldata.h,v 1.3 1998/05/17 18:53:07 tegge Exp $
*/ */
/* /*
@@ -53,7 +53,7 @@ struct globaldata {
u_int cpu_lockid; u_int cpu_lockid;
u_int other_cpus; u_int other_cpus;
pd_entry_t *my_idlePTD; pd_entry_t *my_idlePTD;
u_int ss_tpr; u_int ss_eflags;
pt_entry_t *prv_CMAP1; pt_entry_t *prv_CMAP1;
pt_entry_t *prv_CMAP2; pt_entry_t *prv_CMAP2;
pt_entry_t *prv_CMAP3; pt_entry_t *prv_CMAP3;
+2 -2
View File
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: globaldata.h,v 1.2 1998/04/06 18:59:15 peter Exp $ * $Id: globaldata.h,v 1.3 1998/05/17 18:53:07 tegge Exp $
*/ */
/* /*
@@ -53,7 +53,7 @@ struct globaldata {
u_int cpu_lockid; u_int cpu_lockid;
u_int other_cpus; u_int other_cpus;
pd_entry_t *my_idlePTD; pd_entry_t *my_idlePTD;
u_int ss_tpr; u_int ss_eflags;
pt_entry_t *prv_CMAP1; pt_entry_t *prv_CMAP1;
pt_entry_t *prv_CMAP2; pt_entry_t *prv_CMAP2;
pt_entry_t *prv_CMAP3; pt_entry_t *prv_CMAP3;