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>