Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Feb 2003 05:49:12 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        David Schultz <dschultz@uclink.Berkeley.EDU>
Cc:        smp@FreeBSD.ORG
Subject:   Re: machine/critical.h and !__GNUC__, interrupt nesting level, etc.
Message-ID:  <20030210045401.I2223-100000@gamplex.bde.org>
In-Reply-To: <20030209152414.GA1390@HAL9000.homeunix.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 9 Feb 2003, David Schultz wrote:

> It seems that each src/sys/$arch/$arch/critical.h contains the
> following:
>
> 	#else /* !__GNUC__ */
>
> 	void cpu_critical_enter(void)
> 	void cpu_critical_exit(void)
>
> 	#endif  /* __GNUC__ */
>
> Am I losing my mind or will that cause a compile-time error
> without semicolons at the ends of the lines?  There doesn't even

As you can see, the !__GNUC__ case is rarely tested.

> seem to be a !__GNUC__ implementation at all, or any irreparable
> gccisms in the normal version for that matter.

Rev.1.1 of the i386 version was more complicated and had intr_disable()
calls.  Even that is not a gccism since intr_disable()'s interface is
not gcc-specific; the function is just implemented using gccism in the
__GNUC__ case, and the details for that are elsewhere.  Disabling all
interrupts in these functions is basically a mistake, but may be needed
for unpolished implementations or recalcitrant arches.

> Another random question that came up while I was browsing the
> source entirely too late at night:
>
> Why isn't td_intr_nesting_level bounded?  Isn't there a danger of
> overflowing the kernel stack?

In RELENG_4, the corresponding variable (intr_nesting_level) is bounded
by the number of bits in intrmask_t (since every nested interrupt must
set an unset bit in cpl), and more strictly by the number and arrangement
of splfoo()'s (since bits in cpl are mostly set more than 1 at a time
by splfoo()).  That was intended to give a small enough bound but
probably didn't for the worst case (especially before the kernel stack
size was increased a year or two ago).

In -current, interrupts are rarely if ever nested, since most interrupt
handling is done in interrupt tasks on separate stacks and switches
to the separate stacks are mostly done with interrupts disabled (perhaps
only in software).  I think interrupt nesting essentially _never_
occurs.  There is one special setup where I think it does: if we are
running an interrupt handler with interrupts only masked in software,
then a hardware interrupt may occur of course, and fast interrupts and
maybe some IPIs are allowed to proceed, but there can be no further nesting
since interrupts are then masked in hardware.

td_intr_nesting_level ends up being almost useless.  It is needed to
completely classify interrupt context in statclock() (most cases are
classified by (td->td_ithd != NULL), but the special setup mentioned
above is tricky).  It is used to check for malloc(M_WAITOK) in interrupt
context, but this is bogus -- normal interrupt context is classify
(td->td_ithd != NULL), and just calling malloc() is an error if
td_intr_nesting_level is nonzero (this means that the context is fast
interrupt handler or context-switching context).  Old versions of
SMPng fudged p_intr_nesting_level by setting it to 1 in ithread context,
so the malloc() check was once less bogus.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-smp" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030210045401.I2223-100000>