diff options
author | fsmp <fsmp@FreeBSD.org> | 1997-08-24 00:05:37 +0000 |
---|---|---|
committer | fsmp <fsmp@FreeBSD.org> | 1997-08-24 00:05:37 +0000 |
commit | 618ef60cbd7b8b77d94128a1512d8332bdd69108 (patch) | |
tree | 4729e2ae70430cc50843ab3f87b9f48f20fa6957 /sys/i386/isa | |
parent | fc8b5b4955e847d86a82903f1e573bba3a391e5b (diff) | |
download | FreeBSD-src-618ef60cbd7b8b77d94128a1512d8332bdd69108.zip FreeBSD-src-618ef60cbd7b8b77d94128a1512d8332bdd69108.tar.gz |
The last of the encapsolation of cpl/spl/ipending things into a critical
region protected by the simplelock 'cpl_lock'.
Notes:
- this code is currently controlled on a section by section basis with
defines in machine/param.h. All sections are currently enabled.
- this code is not as clean as I would like, but that can wait till later.
- the "giant lock" still surrounds most instances of this "cpl region".
I still have to do the code that arbitrates setting cpl between the
top and bottom halves of the kernel.
- the possibility of deadlock exists, I am committing the code at this
point so as to exercise it and detect any such cases B4 the "giant lock"
is removed.
Diffstat (limited to 'sys/i386/isa')
-rw-r--r-- | sys/i386/isa/apic_ipl.s | 113 | ||||
-rw-r--r-- | sys/i386/isa/apic_vector.s | 65 | ||||
-rw-r--r-- | sys/i386/isa/icu_ipl.s | 69 | ||||
-rw-r--r-- | sys/i386/isa/ipl.s | 138 | ||||
-rw-r--r-- | sys/i386/isa/ipl_funcs.c | 161 |
5 files changed, 411 insertions, 135 deletions
diff --git a/sys/i386/isa/apic_ipl.s b/sys/i386/isa/apic_ipl.s index a36c4de..ec9b94f 100644 --- a/sys/i386/isa/apic_ipl.s +++ b/sys/i386/isa/apic_ipl.s @@ -22,13 +22,29 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apic_ipl.s,v 1.23 1997/08/21 04:52:30 smp Exp smp $ + * $Id: apic_ipl.s,v 1.28 1997/08/23 05:15:12 smp Exp smp $ */ +#if defined(SMP) && defined(REAL_AICPL) + +#define AICPL_LOCK SCPL_LOCK +#define AICPL_UNLOCK SCPL_UNLOCK + +#else /* SMP */ + +#define AICPL_LOCK +#define AICPL_UNLOCK + +#endif /* SMP */ + .data ALIGN_DATA +/* current INTerrupt level */ + .globl _cil +_cil: .long 0 + /* this allows us to change the 8254 APIC pin# assignment */ .globl _Xintr8254 _Xintr8254: @@ -46,31 +62,6 @@ _vec: .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15 .long vec16, vec17, vec18, vec19, vec20, vec21, vec22, vec23 -/* various simple locks */ - .align 2 /* MUST be 32bit aligned */ - -#if 0 -/* critical region around IO APIC */ - .globl _imen_lock -_imen_lock: - .long 0 - -/* critical region around spl & cpl */ - .globl _cpl_lock -_cpl_lock: - .long 0 - -/* critical region around FAST_INTR() routines */ - .globl _fast_intr_lock -_fast_intr_lock: - .long 0 - -/* critical region around INTR() routines */ - .globl _intr_lock -_intr_lock: - .long 0 -#endif - /* * Note: * This is the UP equivilant of _imen. @@ -83,10 +74,12 @@ _intr_lock: * MAYBE_UNMASK_IRQ * imen_dump() */ + .align 2 /* MUST be 32bit aligned */ .globl _apic_imen _apic_imen: .long HWI_MASK + /* * */ @@ -94,6 +87,74 @@ _apic_imen: SUPERALIGN_TEXT /* + * Interrupt priority mechanism + * -- soft splXX masks with group mechanism (cpl) + * -- h/w masks for currently active or unused interrupts (imen) + * -- ipending = active interrupts currently masked by cpl + */ + +ENTRY(splz) + /* + * The caller has restored cpl and checked that (ipending & ~cpl) + * is nonzero. We have to repeat the check since if there is an + * interrupt while we're looking, _doreti processing for the + * interrupt will handle all the unmasked pending interrupts + * because we restored early. We're repeating the calculation + * of (ipending & ~cpl) anyway so that the caller doesn't have + * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" + * is undefined when %ecx is 0 so we can't rely on the secondary + * btrl tests. + */ + AICPL_LOCK + movl _cpl,%eax +splz_next: + /* + * We don't need any locking here. (ipending & ~cpl) cannot grow + * while we're looking at it - any interrupt will shrink it to 0. + */ + movl %eax,%ecx + notl %ecx /* set bit = unmasked level */ + andl _ipending,%ecx /* set bit = unmasked pending INT */ + jne splz_unpend + AICPL_UNLOCK + ret + + ALIGN_TEXT +splz_unpend: + bsfl %ecx,%ecx + lock + btrl %ecx, _ipending + jnc splz_next + movl ihandlers(,%ecx,4),%edx + testl %edx,%edx + je splz_next /* "can't happen" */ + cmpl $NHWI,%ecx + jae splz_swi + AICPL_UNLOCK + /* + * We would prefer to call the intr handler directly here but that + * doesn't work for badly behaved handlers that want the interrupt + * frame. Also, there's a problem determining the unit number. + * We should change the interface so that the unit number is not + * determined at config time. + */ + jmp *_vec(,%ecx,4) + + ALIGN_TEXT +splz_swi: + cmpl $SWI_AST,%ecx + je splz_next /* "can't happen" */ + pushl %eax + orl imasks(,%ecx,4),%eax + movl %eax,_cpl + AICPL_UNLOCK + call %edx + AICPL_LOCK + popl %eax + movl %eax,_cpl + jmp splz_next + +/* * Fake clock interrupt(s) so that they appear to come from our caller instead * of from here, so that system profiling works. * XXX do this more generally (for all vectors; look up the C entry point). diff --git a/sys/i386/isa/apic_vector.s b/sys/i386/isa/apic_vector.s index 9d1d4a0..71c341d 100644 --- a/sys/i386/isa/apic_vector.s +++ b/sys/i386/isa/apic_vector.s @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: apic_vector.s,v 1.24 1997/08/21 04:52:30 smp Exp smp $ + * $Id: apic_vector.s,v 1.27 1997/08/23 05:15:12 smp Exp smp $ */ @@ -11,6 +11,18 @@ #include "i386/isa/intr_machdep.h" +#if defined(SMP) && defined(REAL_AVCPL) + +#define AVCPL_LOCK CPL_LOCK +#define AVCPL_UNLOCK CPL_UNLOCK + +#else + +#define AVCPL_LOCK +#define AVCPL_UNLOCK + +#endif + #ifdef FAST_SIMPLELOCK #define GET_FAST_INTR_LOCK \ @@ -82,7 +94,7 @@ IDTVEC(vec_name) ; \ popl %eax ; \ iret -#else +#else /* FAST_WITHOUTCPL */ #define FAST_INTR(irq_num, vec_name) \ .text ; \ @@ -93,21 +105,23 @@ IDTVEC(vec_name) ; \ pushl %edx ; \ pushl %ds ; \ MAYBE_PUSHL_ES ; \ - movl $KDSEL,%eax ; \ - movl %ax,%ds ; \ + movl $KDSEL, %eax ; \ + movl %ax, %ds ; \ MAYBE_MOVW_AX_ES ; \ FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ GET_FAST_INTR_LOCK ; \ pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - addl $4,%esp ; \ + addl $4, %esp ; \ movl $0, lapic_eoi ; \ + lock ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ + lock ; \ incl (%eax) ; \ - movl _cpl,%eax ; /* unmasking pending HWIs or SWIs? */ \ + movl _cpl, %eax ; /* unmasking pending HWIs or SWIs? */ \ notl %eax ; \ - andl _ipending,%eax ; \ + andl _ipending, %eax ; \ jne 2f ; /* yes, maybe handle them */ \ 1: ; \ MEXITCOUNT ; \ @@ -121,27 +135,28 @@ IDTVEC(vec_name) ; \ ; \ ALIGN_TEXT ; \ 2: ; \ - cmpb $3,_intr_nesting_level ; /* enough stack? */ \ + cmpb $3, _intr_nesting_level ; /* enough stack? */ \ jae 1b ; /* no, return */ \ - movl _cpl,%eax ; \ + movl _cpl, %eax ; \ /* XXX next line is probably unnecessary now. */ \ - movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \ + movl $HWI_MASK|SWI_MASK, _cpl ; /* limit nesting ... */ \ + lock ; \ incb _intr_nesting_level ; /* ... really limit it ... */ \ sti ; /* to do this as early as possible */ \ MAYBE_POPL_ES ; /* discard most of thin frame ... */ \ popl %ecx ; /* ... original %ds ... */ \ popl %edx ; \ - xchgl %eax,4(%esp) ; /* orig %eax; save cpl */ \ + xchgl %eax, 4(%esp) ; /* orig %eax; save cpl */ \ pushal ; /* build fat frame (grrr) ... */ \ pushl %ecx ; /* ... actually %ds ... */ \ pushl %es ; \ - movl $KDSEL,%eax ; \ - movl %ax,%es ; \ - movl (2+8+0)*4(%esp),%ecx ; /* %ecx from thin frame ... */ \ - movl %ecx,(2+6)*4(%esp) ; /* ... to fat frame ... */ \ - movl (2+8+1)*4(%esp),%eax ; /* ... cpl from thin frame */ \ + movl $KDSEL, %eax ; \ + movl %ax, %es ; \ + movl (2+8+0)*4(%esp), %ecx ; /* %ecx from thin frame ... */ \ + movl %ecx, (2+6)*4(%esp) ; /* ... to fat frame ... */ \ + movl (2+8+1)*4(%esp), %eax ; /* ... cpl from thin frame */ \ pushl %eax ; \ - subl $4,%esp ; /* junk for unit number */ \ + subl $4, %esp ; /* junk for unit number */ \ MEXITCOUNT ; \ jmp _doreti @@ -215,11 +230,11 @@ IDTVEC(vec_name) ; \ testl %eax, %eax ; /* did we get it? */ \ jz 1f ; /* no */ \ ; \ - CPL_LOCK ; /* MP-safe */ \ + AVCPL_LOCK ; /* MP-safe */ \ testl $IRQ_BIT(irq_num), _cpl ; \ - jne 2f ; \ + jne 2f ; /* this INT masked */ \ orl $IRQ_BIT(irq_num), _cil ; \ - CPL_UNLOCK ; \ + AVCPL_UNLOCK ; \ ; \ movl $0, lapic_eoi ; /* XXX too soon? */ \ incb _intr_nesting_level ; \ @@ -229,12 +244,12 @@ __CONCAT(Xresume,irq_num): ; \ movl _intr_countp + (irq_num) * 4, %eax ; \ lock ; incl (%eax) ; \ ; \ - CPL_LOCK ; /* MP-safe */ \ + AVCPL_LOCK ; /* MP-safe */ \ movl _cpl, %eax ; \ pushl %eax ; \ orl _intr_mask + (irq_num) * 4, %eax ; \ movl %eax, _cpl ; \ - CPL_UNLOCK ; \ + AVCPL_UNLOCK ; \ ; \ pushl _intr_unit + (irq_num) * 4 ; \ sti ; \ @@ -252,16 +267,16 @@ __CONCAT(Xresume,irq_num): ; \ MASK_LEVEL_IRQ(irq_num) ; \ movl $0, lapic_eoi ; /* do the EOI */ \ ; \ - CPL_LOCK ; /* MP-safe */ \ + AVCPL_LOCK ; /* MP-safe */ \ orl $IRQ_BIT(irq_num), _ipending ; \ - CPL_UNLOCK ; \ + AVCPL_UNLOCK ; \ ; \ POP_FRAME ; \ iret ; \ ; \ ALIGN_TEXT ; \ 2: ; /* masked by cpl */ \ - CPL_UNLOCK ; \ + AVCPL_UNLOCK ; \ ISR_RELLOCK ; /* XXX this is going away... */ \ jmp 1b diff --git a/sys/i386/isa/icu_ipl.s b/sys/i386/isa/icu_ipl.s index 3790f0f..2dc0e8d 100644 --- a/sys/i386/isa/icu_ipl.s +++ b/sys/i386/isa/icu_ipl.s @@ -34,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: icu_ipl.s,v 1.1 1997/05/24 17:02:04 smp Exp smp $ + * $Id: icu_ipl.s,v 1.2 1997/08/22 05:05:05 smp Exp smp $ */ .data @@ -45,6 +45,11 @@ _vec: .long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7 .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15 +/* interrupt mask enable (all h/w off) */ + .globl _imen +_imen: .long HWI_MASK + + /* * */ @@ -52,6 +57,68 @@ _vec: SUPERALIGN_TEXT /* + * Interrupt priority mechanism + * -- soft splXX masks with group mechanism (cpl) + * -- h/w masks for currently active or unused interrupts (imen) + * -- ipending = active interrupts currently masked by cpl + */ + +ENTRY(splz) + /* + * The caller has restored cpl and checked that (ipending & ~cpl) + * is nonzero. We have to repeat the check since if there is an + * interrupt while we're looking, _doreti processing for the + * interrupt will handle all the unmasked pending interrupts + * because we restored early. We're repeating the calculation + * of (ipending & ~cpl) anyway so that the caller doesn't have + * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" + * is undefined when %ecx is 0 so we can't rely on the secondary + * btrl tests. + */ + movl _cpl,%eax +splz_next: + /* + * We don't need any locking here. (ipending & ~cpl) cannot grow + * while we're looking at it - any interrupt will shrink it to 0. + */ + movl %eax,%ecx + notl %ecx + andl _ipending,%ecx + jne splz_unpend + ret + + ALIGN_TEXT +splz_unpend: + bsfl %ecx,%ecx + btrl %ecx,_ipending + jnc splz_next + movl ihandlers(,%ecx,4),%edx + testl %edx,%edx + je splz_next /* "can't happen" */ + cmpl $NHWI,%ecx + jae splz_swi + /* + * We would prefer to call the intr handler directly here but that + * doesn't work for badly behaved handlers that want the interrupt + * frame. Also, there's a problem determining the unit number. + * We should change the interface so that the unit number is not + * determined at config time. + */ + jmp *_vec(,%ecx,4) + + ALIGN_TEXT +splz_swi: + cmpl $SWI_AST,%ecx + je splz_next /* "can't happen" */ + pushl %eax + orl imasks(,%ecx,4),%eax + movl %eax,_cpl + call %edx + popl %eax + movl %eax,_cpl + jmp splz_next + +/* * Fake clock interrupt(s) so that they appear to come from our caller instead * of from here, so that system profiling works. * XXX do this more generally (for all vectors; look up the C entry point). diff --git a/sys/i386/isa/ipl.s b/sys/i386/isa/ipl.s index 82ca3b9..6393882 100644 --- a/sys/i386/isa/ipl.s +++ b/sys/i386/isa/ipl.s @@ -36,10 +36,24 @@ * * @(#)ipl.s * - * $Id: ipl.s,v 1.8 1997/08/20 19:46:22 smp Exp $ + * $Id: ipl.s,v 1.13 1997/08/23 05:15:12 smp Exp smp $ */ +#if defined(SMP) && defined(REAL_ICPL) + +#define ICPL_LOCK CPL_LOCK +#define ICPL_UNLOCK CPL_UNLOCK +#define FAST_ICPL_UNLOCK movl $0, _cpl_lock + +#else /* SMP */ + +#define ICPL_LOCK +#define ICPL_UNLOCK +#define FAST_ICPL_UNLOCK + +#endif /* SMP */ + /* * AT/386 * Vector interrupt control section @@ -52,16 +66,6 @@ .globl _cpl _cpl: .long HWI_MASK | SWI_MASK -/* current INTerrupt level */ - .globl _cil -_cil: .long 0 - -#ifndef APIC_IO -/* interrupt mask enable (all h/w off) */ - .globl _imen -_imen: .long HWI_MASK -#endif /* APIC_IO */ - .globl _tty_imask _tty_imask: .long 0 .globl _bio_imask @@ -75,9 +79,9 @@ _softnet_imask: .long SWI_NET_MASK .globl _softtty_imask _softtty_imask: .long SWI_TTY_MASK - .globl _ipending /* pending interrupts blocked by splxxx() */ + .globl _ipending _ipending: .long 0 /* set with bits for which queue to service */ @@ -115,14 +119,23 @@ doreti_next: * so that the stack cannot pile up (the nesting level of interrupt * handlers is limited by the number of bits in cpl). */ +#ifdef SMP + cli /* early to prevent INT deadlock */ + movl %eax, %edx /* preserve cpl while getting lock */ + ICPL_LOCK + movl %edx, %eax +#endif movl %eax,%ecx - notl %ecx + notl %ecx /* set bit = unmasked level */ +#ifndef SMP cli - andl _ipending,%ecx +#endif + andl _ipending,%ecx /* set bit = unmasked pending INT */ jne doreti_unpend doreti_exit: movl %eax,_cpl - decb _intr_nesting_level + FAST_ICPL_UNLOCK /* preserves %eax */ + MPLOCKED decb _intr_nesting_level MEXITCOUNT #ifdef VM86 /* @@ -132,6 +145,7 @@ doreti_exit: * vm86 mode. doreti_stop is a convenient place to set a breakpoint. * When the cpl problem is solved, this code can disappear. */ + ICPL_LOCK cmpl $0,_cpl je 1f testl $PSL_VM,TF_EFLAGS(%esp) @@ -140,6 +154,7 @@ doreti_stop: movl $0,_cpl nop 1: + FAST_ICPL_UNLOCK /* preserves %eax */ #endif /* VM86 */ #ifdef SMP @@ -184,9 +199,17 @@ doreti_unpend: * We won't miss any new pending interrupts because we will check * for them again. */ +#ifdef SMP + /* we enter with cpl locked */ + bsfl %ecx, %ecx /* slow, but not worth optimizing */ + btrl %ecx, _ipending + FAST_ICPL_UNLOCK /* preserves %eax */ + sti /* late to prevent INT deadlock */ +#else sti bsfl %ecx,%ecx /* slow, but not worth optimizing */ - MPLOCKED btrl %ecx, _ipending + btrl %ecx,_ipending +#endif /* SMP */ jnc doreti_next /* some intr cleared memory copy */ movl ihandlers(,%ecx,4),%edx testl %edx,%edx @@ -194,7 +217,14 @@ doreti_unpend: cmpl $NHWI,%ecx jae doreti_swi cli +#ifdef SMP + pushl %eax /* preserve %eax */ + ICPL_LOCK + popl _cpl + FAST_ICPL_UNLOCK +#else movl %eax,_cpl +#endif MEXITCOUNT jmp %edx @@ -210,8 +240,18 @@ doreti_swi: * interrupt frames. There are only 4 different SWIs and the HWI * and SWI masks limit the nesting further. */ +#ifdef SMP + orl imasks(,%ecx,4), %eax + cli /* prevent INT deadlock */ + pushl %eax /* save cpl */ + ICPL_LOCK + popl _cpl /* restore cpl */ + FAST_ICPL_UNLOCK + sti +#else orl imasks(,%ecx,4),%eax movl %eax,_cpl +#endif call %edx popl %eax jmp doreti_next @@ -247,72 +287,12 @@ swi_ast_phantom: * using by using cli, but they are unavoidable for lcall entries. */ cli - MPLOCKED orl $SWI_AST_PENDING, _ipending + ICPL_LOCK + orl $SWI_AST_PENDING, _ipending + /* cpl is unlocked in doreti_exit */ subl %eax,%eax jmp doreti_exit /* SWI_AST is highest so we must be done */ -/* - * Interrupt priority mechanism - * -- soft splXX masks with group mechanism (cpl) - * -- h/w masks for currently active or unused interrupts (imen) - * -- ipending = active interrupts currently masked by cpl - */ - -ENTRY(splz) - /* - * The caller has restored cpl and checked that (ipending & ~cpl) - * is nonzero. We have to repeat the check since if there is an - * interrupt while we're looking, _doreti processing for the - * interrupt will handle all the unmasked pending interrupts - * because we restored early. We're repeating the calculation - * of (ipending & ~cpl) anyway so that the caller doesn't have - * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" - * is undefined when %ecx is 0 so we can't rely on the secondary - * btrl tests. - */ - movl _cpl,%eax -splz_next: - /* - * We don't need any locking here. (ipending & ~cpl) cannot grow - * while we're looking at it - any interrupt will shrink it to 0. - */ - movl %eax,%ecx - notl %ecx - andl _ipending,%ecx - jne splz_unpend - ret - - ALIGN_TEXT -splz_unpend: - bsfl %ecx,%ecx - MPLOCKED btrl %ecx, _ipending - jnc splz_next - movl ihandlers(,%ecx,4),%edx - testl %edx,%edx - je splz_next /* "can't happen" */ - cmpl $NHWI,%ecx - jae splz_swi - /* - * We would prefer to call the intr handler directly here but that - * doesn't work for badly behaved handlers that want the interrupt - * frame. Also, there's a problem determining the unit number. - * We should change the interface so that the unit number is not - * determined at config time. - */ - jmp *_vec(,%ecx,4) - - ALIGN_TEXT -splz_swi: - cmpl $SWI_AST,%ecx - je splz_next /* "can't happen" */ - pushl %eax - orl imasks(,%ecx,4),%eax - movl %eax,_cpl - call %edx - popl %eax - movl %eax,_cpl - jmp splz_next - ALIGN_TEXT swi_net: diff --git a/sys/i386/isa/ipl_funcs.c b/sys/i386/isa/ipl_funcs.c index c0849cd..60cfb27 100644 --- a/sys/i386/isa/ipl_funcs.c +++ b/sys/i386/isa/ipl_funcs.c @@ -23,13 +23,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ipl_funcs.c,v 1.1 1997/05/31 08:57:05 peter Exp $ + * $Id: ipl_funcs.c,v 1.6 1997/08/23 23:15:19 smp Exp smp $ */ #include <sys/types.h> #include <sys/systm.h> #include <machine/ipl.h> +#ifndef SMP /* * The volatile bitmap variables must be set atomically. This normally * involves using a machine-dependent bit-set or `or' instruction. @@ -93,12 +94,164 @@ splx(unsigned ipl) splz(); } -#ifdef SMP +#else /* !SMP */ + +#include <machine/param.h> +#include <machine/smp.h> + +#if defined(REAL_IFCPL) + +#define IFCPL_LOCK() SCPL_LOCK() +#define IFCPL_UNLOCK() SCPL_UNLOCK() + +#else /* REAL_IFCPL */ + +#define IFCPL_LOCK() +#define IFCPL_UNLOCK() + +#endif /* REAL_IFCPL */ + +/* + * The volatile bitmap variables must be set atomically. This normally + * involves using a machine-dependent bit-set or `or' instruction. + */ + +#define DO_SETBITS(name, var, bits) \ +void name(void) \ +{ \ + IFCPL_LOCK(); \ + setbits(var, bits); \ + IFCPL_UNLOCK(); \ +} + +DO_SETBITS(setdelayed, &ipending, loadandclear((unsigned *)&idelayed)) +DO_SETBITS(setsoftast, &ipending, SWI_AST_PENDING) +DO_SETBITS(setsoftclock, &ipending, SWI_CLOCK_PENDING) +DO_SETBITS(setsoftnet, &ipending, SWI_NET_PENDING) +DO_SETBITS(setsofttty, &ipending, SWI_TTY_PENDING) + +DO_SETBITS(schedsoftnet, &idelayed, SWI_NET_PENDING) +DO_SETBITS(schedsofttty, &idelayed, SWI_TTY_PENDING) + +unsigned +softclockpending(void) +{ + unsigned x; + + IFCPL_LOCK(); + x = ipending & SWI_CLOCK_PENDING; + IFCPL_UNLOCK(); + + return x; +} + + +#define GENSPL(name, set_cpl) \ +unsigned name(void) \ +{ \ + unsigned x; \ + \ + IFCPL_LOCK(); \ + x = cpl; \ + /* XXX test cil */ \ + set_cpl; \ + IFCPL_UNLOCK(); \ + \ + return (x); \ +} + +GENSPL(splbio, cpl |= bio_imask) +GENSPL(splclock, cpl = HWI_MASK | SWI_MASK) +GENSPL(splimp, cpl |= net_imask) +GENSPL(splnet, cpl |= SWI_NET_MASK) +GENSPL(splsoftclock, cpl = SWI_CLOCK_MASK) +GENSPL(splsofttty, cpl |= SWI_TTY_MASK) +GENSPL(splstatclock, cpl |= stat_imask) +GENSPL(splvm, cpl |= net_imask | bio_imask) + + +/* + * This version has to check for smp_active, + * as calling simple_lock() (ie ss_lock) before then deadlocks the system. + */ +#define GENSPL2(name, set_cpl) \ +unsigned name(void) \ +{ \ + unsigned x; \ + \ + if (smp_active) \ + IFCPL_LOCK(); \ + x = cpl; \ + /* XXX test cil */ \ + set_cpl; \ + if (smp_active) \ + IFCPL_UNLOCK(); \ + \ + return (x); \ +} + +GENSPL2(splhigh, cpl = HWI_MASK | SWI_MASK) +GENSPL2(spltty, cpl |= tty_imask) + + +void +spl0(void) +{ + IFCPL_LOCK(); + + /* XXX test cil */ + cpl = SWI_AST_MASK; + if (ipending & ~SWI_AST_MASK) { + IFCPL_UNLOCK(); + splz(); + } + else + IFCPL_UNLOCK(); +} + +void +splx(unsigned ipl) +{ + if (smp_active) + IFCPL_LOCK(); + + /* XXX test cil */ + cpl = ipl; + if (ipending & ~ipl) { + if (smp_active) + IFCPL_UNLOCK(); + splz(); + } + else + if (smp_active) + IFCPL_UNLOCK(); +} + + +/* + * Replaces UP specific inline found in (?) pci/pci_support.c. + * + * Stefan said: + * You know, that splq() is used in the shared interrupt multiplexer, and that + * the SMP version should not have too much overhead. If it is significantly + * slower, then moving the splq() out of the loop in intr_mux() and passing in + * the logical OR of all mask values might be a better solution than the + * current code. (This logical OR could of course be pre-calculated whenever + * another shared interrupt is registered ...) + */ intrmask_t splq(intrmask_t mask) { - intrmask_t tmp = cpl; + intrmask_t tmp; + + IFCPL_LOCK(); + + tmp = cpl; cpl |= mask; + + IFCPL_UNLOCK(); + return (tmp); } -#endif + +#endif /* !SMP */ |