ipl_funcs.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 463 行

C
463
字号
/*- * Copyright (c) 1997 Bruce Evans. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	$\Id: ipl_funcs.c,v 1.14 1998/12/07 21:58:22 archie Exp $ */#include <sys/types.h>#include <sys/systm.h>#include <machine/ipl.h>#ifndef SMP#ifdef OSKIT#include "osenv.h"#define NOIDELAYEDunsigned oskit_freebsd_cpl;unsigned oskit_freebsd_ipending;unsigned oskit_freebsd_idelayed;#define cpl oskit_freebsd_cpl#define ipending oskit_freebsd_ipending#ifdef NOIDELAYED#define idelayed oskit_freebsd_ipending#else#define idelayed oskit_freebsd_idelayed#endif#endif/* * 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)					\{						\	setbits(var, bits);			\}#ifdef NOIDELAYEDvoid setdelayed(void) {};#elseDO_SETBITS(setdelayed,   &ipending, loadandclear((unsigned *)&idelayed))#endifDO_SETBITS(setsoftast,   &ipending, SWI_AST_PENDING)DO_SETBITS(setsoftcamnet,&ipending, SWI_CAMNET_PENDING)DO_SETBITS(setsoftcambio,&ipending, SWI_CAMBIO_PENDING)DO_SETBITS(setsoftclock, &ipending, SWI_CLOCK_PENDING)DO_SETBITS(setsoftnet,   &ipending, SWI_NET_PENDING)DO_SETBITS(setsofttty,   &ipending, SWI_TTY_PENDING)DO_SETBITS(setsoftvm,	 &ipending, SWI_VM_PENDING)DO_SETBITS(schedsoftcamnet, &idelayed, SWI_CAMNET_PENDING)DO_SETBITS(schedsoftcambio, &idelayed, SWI_CAMBIO_PENDING)DO_SETBITS(schedsoftnet, &idelayed, SWI_NET_PENDING)DO_SETBITS(schedsofttty, &idelayed, SWI_TTY_PENDING)DO_SETBITS(schedsoftvm,	&idelayed, SWI_VM_PENDING)unsignedsoftclockpending(void){	return (ipending & SWI_CLOCK_PENDING);}#ifdef OSKIT#define	GENSPL(name, set_cpl) \unsigned name(void)				\{						\	unsigned x;				\						\	osenv_intr_disable();			\	x = cpl;				\	cpl = 1;				\	return (x);				\}#else#define	GENSPL(name, set_cpl) \unsigned name(void)				\{						\	unsigned x;				\						\	x = cpl;				\	set_cpl;				\	return (x);				\}#endifGENSPL(splbio, cpl |= bio_imask)GENSPL(splcam, cpl |= cam_imask)GENSPL(splclock, cpl = HWI_MASK | SWI_MASK)GENSPL(splhigh, cpl = HWI_MASK | SWI_MASK)GENSPL(splimp, cpl |= net_imask)GENSPL(splnet, cpl |= SWI_NET_MASK)GENSPL(splsoftcam, cpl |= SWI_CAMBIO_MASK | SWI_CAMNET_MASK)GENSPL(splsoftcambio, cpl |= SWI_CAMBIO_MASK)GENSPL(splsoftcamnet, cpl |= SWI_CAMNET_MASK)GENSPL(splsoftclock, cpl = SWI_CLOCK_MASK)GENSPL(splsofttty, cpl |= SWI_TTY_MASK)GENSPL(splsoftvm, cpl |= SWI_VM_MASK)GENSPL(splstatclock, cpl |= stat_imask)GENSPL(spltty, cpl |= tty_imask)GENSPL(splvm, cpl |= net_imask | bio_imask)#ifdef OSKITvoidspl0(void){	splx(0);}voidsplx(unsigned ipl){	if (ipl == 0) {		cpl = 0;		osenv_intr_enable();	}}#elsevoidspl0(void){	cpl = SWI_AST_MASK;	if (ipending & ~SWI_AST_MASK)		splz();}voidsplx(unsigned ipl){	cpl = ipl;	if (ipending & ~ipl)		splz();}#endif /* !OSKIT */#else /* !SMP */#error "Code broken for SMP and the OSKIT"#include <machine/smp.h>#include <machine/smptests.h>#ifndef SPL_DEBUG_POSTCODE#undef POSTCODE#undef POSTCODE_LO#undef POSTCODE_HI#define POSTCODE(X)#define POSTCODE_LO(X)#define POSTCODE_HI(X)#endif /* SPL_DEBUG_POSTCODE *//* * 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(setsoftcamnet,&ipending, SWI_CAMNET_PENDING)DO_SETBITS(setsoftcambio,&ipending, SWI_CAMBIO_PENDING)DO_SETBITS(setsoftclock, &ipending, SWI_CLOCK_PENDING)DO_SETBITS(setsoftnet,   &ipending, SWI_NET_PENDING)DO_SETBITS(setsofttty,   &ipending, SWI_TTY_PENDING)DO_SETBITS(setsoftvm,	 &ipending, SWI_VM_PENDING)DO_SETBITS(schedsoftcamnet, &idelayed, SWI_CAMNET_PENDING)DO_SETBITS(schedsoftcambio, &idelayed, SWI_CAMBIO_PENDING)DO_SETBITS(schedsoftnet, &idelayed, SWI_NET_PENDING)DO_SETBITS(schedsofttty, &idelayed, SWI_TTY_PENDING)DO_SETBITS(schedsoftvm,	&idelayed, SWI_VM_PENDING)unsignedsoftclockpending(void){	unsigned x;	IFCPL_LOCK();	x = ipending & SWI_CLOCK_PENDING;	IFCPL_UNLOCK();	return (x);}/* * This version has to check for bsp_apic_ready, * as calling simple_lock() (ie ss_lock) before then deadlocks the system. * A sample count of GENSPL calls before bsp_apic_ready was set: 2193 */#ifdef INTR_SPL#ifdef SPL_DEBUG#define MAXZ		100000000#define SPIN_VAR	unsigned z;#define SPIN_RESET	z = 0;#if 0#define SPIN_SPL							\			if (++z >= MAXZ) {				\				/* XXX allow lock-free panic */		\				bsp_apic_ready = 0;			\				panic("\ncil: 0x%08x", cil);		\			}#else#define SPIN_SPL							\			if (++z >= MAXZ) {				\				/* XXX allow lock-free panic */		\				bsp_apic_ready = 0;			\				printf("\ncil: 0x%08x", cil);		\				breakpoint();				\			}#endif /* 0/1 */#else /* SPL_DEBUG */#define SPIN_VAR#define SPIN_RESET#define SPIN_SPL#endif /* SPL_DEBUG */#endif#ifdef INTR_SPL#define	GENSPL(NAME, OP, MODIFIER, PC)					\unsigned NAME(void)							\{									\	unsigned x, y;							\	SPIN_VAR;							\									\	if (!bsp_apic_ready) {						\		x = cpl;						\		cpl OP MODIFIER;					\		return (x);						\	}								\									\	for (;;) {							\		IFCPL_LOCK();		/* MP-safe */			\		x = y = cpl;		/* current value */		\		POSTCODE(0x20 | PC);					\		if (inside_intr)					\			break;		/* XXX only 1 INT allowed */	\		y OP MODIFIER;		/* desired value */		\		if (cil & y) {		/* not now */			\			IFCPL_UNLOCK();	/* allow cil to change */	\			SPIN_RESET;					\			while (cil & y)					\				SPIN_SPL				\			continue;	/* try again */			\		}							\		break;							\	}								\	cpl OP MODIFIER;		/* make the change */		\	IFCPL_UNLOCK();							\									\	return (x);							\}/*    NAME:            OP:     MODIFIER:				PC: */GENSPL(splbio,		|=,	bio_imask,				2)GENSPL(splcam,		|=,	cam_imask,				7)GENSPL(splclock,	 =,	HWI_MASK | SWI_MASK,			3)GENSPL(splhigh,		 =,	HWI_MASK | SWI_MASK,			4)GENSPL(splimp,		|=,	net_imask,				5)GENSPL(splnet,		|=,	SWI_NET_MASK,				6)GENSPL(splsoftcam,	|=,	SWI_CAMBIO_MASK | SWI_CAMNET_MASK,	8)GENSPL(splsoftcambio,	|=,	SWI_CAMBIO_MASK,			9)GENSPL(splsoftcamnet, 	|=,	SWI_CAMNET_MASK,			10)GENSPL(splsoftclock,	 =,	SWI_CLOCK_MASK,				11)GENSPL(splsofttty,	|=,	SWI_TTY_MASK,				12)GENSPL(splsoftvm,	|=,	SWI_VM_MASK,				16)GENSPL(splstatclock,	|=,	stat_imask,				13)GENSPL(spltty,		|=,	tty_imask,				14)GENSPL(splvm,		|=,	net_imask | bio_imask,			15)#else /* INTR_SPL */#define	GENSPL(NAME, set_cpl)			\unsigned NAME(void)				\{						\	unsigned x;				\						\	if (!bsp_apic_ready) {			\		x = cpl;			\		set_cpl;			\	}					\	else {					\		IFCPL_LOCK();			\		x = cpl;			\		set_cpl;			\		IFCPL_UNLOCK();			\	}					\						\	return (x);				\}GENSPL(splbio, cpl |= bio_imask)GENSPL(splclock, cpl = HWI_MASK | SWI_MASK)GENSPL(splhigh, cpl = HWI_MASK | SWI_MASK)GENSPL(splimp, cpl |= net_imask)GENSPL(splnet, cpl |= SWI_NET_MASK)GENSPL(splcam, cpl |= cam_imask)GENSPL(splsoftcam, cpl |= SWI_CAMBIO_MASK | SWI_CAMNET_MASK)GENSPL(splsoftcambio, cpl |= SWI_CAMBIO_MASK)GENSPL(splsoftcamnet, cpl |= SWI_CAMNET_MASK)GENSPL(splsoftclock, cpl = SWI_CLOCK_MASK)GENSPL(splsofttty, cpl |= SWI_TTY_MASK)GENSPL(splsoftvm, cpl |= SWI_VM_MASK)GENSPL(splstatclock, cpl |= stat_imask)GENSPL(spltty, cpl |= tty_imask)GENSPL(splvm, cpl |= net_imask | bio_imask)#endif /* INTR_SPL */voidspl0(void){	int unpend;#ifdef INTR_SPL	SPIN_VAR;	for (;;) {		IFCPL_LOCK();		POSTCODE_HI(0xc);		if (cil & SWI_AST_MASK) {	/* not now */			IFCPL_UNLOCK();		/* allow cil to change */			SPIN_RESET;			while (cil & SWI_AST_MASK)				SPIN_SPL			continue;		/* try again */		}		break;	}#else /* INTR_SPL */	IFCPL_LOCK();#endif /* INTR_SPL */	cpl = SWI_AST_MASK;	unpend = ipending & ~SWI_AST_MASK;	IFCPL_UNLOCK();	if (unpend && !inside_intr)		splz();}voidsplx(unsigned ipl){	int unpend;#ifdef INTR_SPL	SPIN_VAR;#endif	if (!bsp_apic_ready) {		cpl = ipl;		if (ipending & ~ipl)			splz();		return;	}#ifdef INTR_SPL	for (;;) {		IFCPL_LOCK();		POSTCODE_HI(0xe);		if (inside_intr)			break;			/* XXX only 1 INT allowed */		POSTCODE_HI(0xf);		if (cil & ipl) {		/* not now */			IFCPL_UNLOCK();		/* allow cil to change */			SPIN_RESET;			while (cil & ipl)				SPIN_SPL			continue;		/* try again */		}		break;	}#else /* INTR_SPL */	IFCPL_LOCK();#endif /* INTR_SPL */	cpl = ipl;	unpend = ipending & ~ipl;	IFCPL_UNLOCK();	if (unpend && !inside_intr)		splz();}/* * 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_tsplq(intrmask_t mask){	intrmask_t tmp;#ifdef INTR_SPL	intrmask_t tmp2;	for (;;) {		IFCPL_LOCK();		tmp = tmp2 = cpl;		tmp2 |= mask;		if (cil & tmp2) {		/* not now */			IFCPL_UNLOCK();		/* allow cil to change */			while (cil & tmp2)				/* spin */ ;			continue;		/* try again */		}		break;	}	cpl = tmp2;#else /* INTR_SPL */	IFCPL_LOCK();	tmp = cpl;	cpl |= mask;#endif /* INTR_SPL */	IFCPL_UNLOCK();	return (tmp);}#endif /* !SMP */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?