Subject: Re: splraiseipl()
To: None <tsutsui@ceres.dti.ne.jp>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 07/01/2006 01:41:37
hi,

> > > - it looks weird a bit to define IPL_* macro as (PSL_S|PSL_IPL?)
> > >   because IPL_* macros are used to specify interrupt priority order
> > >   on some ports (hp300, some mips etc).
> > how are hp300 and mips related to this patch?
> 
> On hp300, IPL_* macros already have some meaning:
> >> /*
> >>  * Interrupt "levels".  These are a more abstract representation
> >>  * of interrupt levels, and do not have the same meaning as m68k
> >>  * CPU interrupt levels.  They serve two purposes:
> >>  *
> >>  *      - properly order ISRs in the list for that CPU ipl
> >>  *      - compute CPU PSL values for the spl*() calls.
> >>  */
> >>#define IPL_NONE        0       /* disable only this interrupt */
>  :
> 
> but in <sys/spl.h> IPL_* macros are used as opaque values passed
> to splraise(). Maybe we should rename either of them, but it
> might cause some confusion to use existing names for splraiseipl(),
> as you wrote in PR/33218.

i'm not sure if i understand your point.
the comment you cited ("compute CPU PSL values for the spl*() calls") is
what an argument of splraiseipl is for.
do you mean hp300 and luna68k should share IPL_xxx values?

> If we introduce new independent SPL_* macros, we could define them like:
> ---
> #define	IPL_NONE	0	/* disable only this interrupt */
> #define	IPL_BIO		1	/* disable block I/O interrupts */
> #define	IPL_NET		2	/* disable network interrupts */
> #define	IPL_TTY		3	/* disable terminal interrupts */
> #define	IPL_TTYNOBUF	4	/* IPL_TTY + higher ISR priority */
> #define	IPL_CLOCK	5	/* disable clock interrupts */
> #define	IPL_HIGH	6	/* disable all interrupts */
>  :
> #define	spllowersoftclock() spl1()
> 
> #define	SPL_SOFTCLOCK	(PSL_S|PSL_IPL1)
> #define	SPL_SOFTNET	(PSL_S|PSL_IPL1)
> #define	SPL_BIO		(hp300_ipls[HP300_IPL_BIO])
> #define	SPL_NET		(hp300_ipls[HP300_IPL_NET])
> #define	SPL_TTY		(hp300_ipls[HP300_IPL_TTY])
> #define	SPL_SERIAL	(hp300_ipls[HP300_IPL_TTY])
> #define	SPL_VM		(hp300_ipls[HP300_IPL_VM])
> #define	SPL_CLOCK	(PSL_S|PSL_IPL6)
> #define	SPL_STATCLOCK	SPL_CLOCK
> #define	SPL_SCHED	(PSL_S|PSL_IPL7)
> #define	SPL_LOCK	(PSL_S|PSL_IPL7)
> #define	SPL_HIGH	(PSL_S|PSL_IPL7)
>  :
> ---
> then all m68k ports could have the same meanings of SPL_*,
> definition of splraiseipl() could be defined as
> "#define splraiseipl(ipl) _splraise(ipl)" in common <m68k/psl.h>.

how about having another opaque type as the following?

- make sure that each IPL_xxx has different values, so that they can
  be converted to SPL_xxx when necessary.
- move a possibly slow part of splraiseipl (eg. IPL_xxx -> SPL_xxx conversion)
  into another function, makeiplcookie(), so that it isn't executed
  frequently.

	/*
	 * ipl_t: IPL_BIO, IPL_NET, ....
	 *
	 * MD type.  maybe int for all ports.
	 */
	typedef int ipl_t;

	/*
	 * ipl_cookie_t:
	 *
	 * MD type.
	 *
	 * for some ports, it can be the same as ipl_t.
	 * for other ports, it can be SPL_xxx, PSL_xxx, etc.
	 */
	typedef xxx ipl_cookie_t;

	int splraiseipl(ipl_cookie_t);

	/*
	 * makeiplcookie:
	 *
	 * calculate a cookie for splraiseipl.
	 *
	 * for some ports, this might do IPL_xxx -> SPL_xxx conversion.
	 */
	ipl_cookie_t makeiplcookie(ipl_t);


the following is an example of their usage.

	typedef struct {
		ipl_cookie_t iplcookie;
		int savedipl;
		struct simplelock lock;
	} lock_t; /* a simple ipl-protected spin lock */

	void
	lk_init(lock_t *lk, ipl_t ipl)
	{

		lk->iplcookie = makeiplcookie(ipl);
		simple_lock_init(&lk->lock);
	}

	void
	lk_acquire(lock_t *lk)
	{
		int s = splraiseipl(lk->iplcookie);
		simple_lock(&lk->lock);
		lk->savedipl = s;
	}

	void
	lk_release(lock_t *lk)
	{
		int s = lk->savedipl;
		simple_unlock(&lk->lock);
		splx(s);
	}

YAMAMOTO Takashi