Subject: Re: splserial() higher than splhigh()?
To: Allen Briggs <briggs@wasabisystems.com>
From: David Querbach <querbach@realtime.bc.ca>
List: tech-kern
Date: 02/01/2001 10:26:37
> This looks good, except that I am somewhat concerned about...
> 
> > 		Loop over the software interrupts until no more are pending
> > 		and unmasked.
> 
> This makes sense, but I am leery of having a loop in the interrupt
> handler.  This is probably just superstition on my part.  If, for
> example, we have a load of serial interrupts coming in, the
> SINT_SERIAL will be almost continually set and this could keep
> looping for quite a while.  Now, maybe this is what you want in
> that case.  You certainly need to take care of it at some point.

I haven't looked, but I expect that the serial software handler (for
example) eventually runs out of buffer space and turns itself off.  This
then allows non-interrupt-handler code to run and unload the buffer.

I'm assuming here that the software handlers are designed to run repeatedly,
if necessary, to handle all pending events.
 
> I presume that you don't mean just "software interrupts" like SINT_*,
> but interrupts that may have been received but masked while processing
> the h/w interrupt.  Is this correct?

Yes, but in my scheme (unlike the current code), the pending hardware
requests are not allowed to genererate interrupts until we are actually
ready to be pre-empted.  We indicate this readiness by enabling external
interrupts in the MSR while actually running the handler code.  We only
disable external interrupts when manipulating the IPL and searching for the
handler to run.

As we go around the loop, hardware interrupts are re-enabled when running a
software interrupt handler.  This software handler can then be interrupted
by a hardware interrupt, causing a hardware interrupt handler to run
immediately.  This hardware handler could then schedule software interrupts. 
These software interrupts, if higher priority than the one we interrupted,
would be serviced before returning from the hardware interrupt to the
interrupted software handler.

Whew.  Perhaps a diagram is in order.  In the following, code with greater
indent is running in an interrupt context with respect to code with lesser
indent.  IPL's increase with increasing interrupt priority.  IPL 0 means all
interrupts enabled.  IPL 1, 2, 3 are software interrupt priorities, and IPL 4
and greater are hardware interrupt priorities.

Case 1:  Nested H/W interrupts during H/W interrupt service:

	...
	regular code with IPL = 0
		level 5 interrupt occurs
		IPL = 5
		ints on
		run h/w handler 5
			level 8 interrupt occurs
			IPL = 8
			ints on
			run h/w handler 8
			ints off
			IPL = 5
			while s/w ints pending with IPL > 5: (none)
			return from level 8 interrupt
		continue h/w handler 5
		ints off
		IPL = 0
		while s/w ints pending with IPL > 0: (none)
		return from level 5 interrupt
	regular code with IPL = 0
	...

Case 2:  S/W handler interrupted by H/W interrupt which schedules a higher
priority S/W interrupt:

	...
	regular code with IPL = 0
		level 5 interrupt occurs
		IPL = 5
		ints on
		run h/w handler 5, which schedules an IPL 2 s/w interrupt
		ints off
		IPL = 0
		while s/w interrupts pending with IPL > 0:
			IPL = 2
			ints on
			run s/w handler 2
				level 8 interrupt occurs
				IPL = 8
				ints on
				run h/w handler 8, schedule IPL 3 s/w irq
				ints off
				IPL = 2
				while s/w ints pending with IPL > 2:
					IPL = 3
					ints on
					run s/w handler 3
					ints off
					IPL = 2
				return from level 8 interrupt
			continue s/w handler 2
			ints off
		return from level 5 interrupt
	regular code with IPL = 0
	...
	
> > This method also allows software interrupt handlers to pre-empt one
> > another, according to their IPL.
> 
> It looks OK to me after some examination, but I'm still getting used to
> this method of handling interrupts.  I'm more used to the m68k with
> more rigid h/w interrupt levels.

We still have rigid H/W levels, but they don't in general correspond to the
IPL.  That's why we have to individually mask sources with IPL's less than
or equal to the new IPL when we raise the IPL, regardless of their H/W
levels.

The H/W levels simply choose between requests when more than one is pending. 
As soon as we re-enable interrupts during an interrupt service, another
interrupt may occur (if it was not masked because its IPL was too low).  By
the time no more unmasked interrupts are pending, we will be running the
service routine with the highest IPL.


By the way, thanks for going through the analysis with me; describing it in
pseudo-code has helped clarify it in my mind.

Regards,

David Querbach
Real-Time Systems Inc.