Subject: Re: splserial() higher than splhigh()?
To: Allen Briggs <briggs@wasabisystems.com>
From: David Querbach <querbach@realtime.bc.ca>
List: tech-kern
Date: 01/31/2001 10:08:10
> The interrupts are disabled by the processor when the exception is taken,
> and are not re-enabled (for some reason, I thought that they were, but I
> don't see it now).
> 
> > For the softint processing, you probably do want to have interrupts
> > re-enabled, but this code obviously doesn't do that.  This would be
> > pretty straight-forward to do.
> 
> ...except for the fact that if you have re-enabled interrupts prior
> to doing the softint processing, it's quite possible that another
> h/w interrupt has come in and been deferred at that point (which you
> may will miss due to the reentrancy check).  You could put a loop here,
> but I don't think you really want that, either.  So this isn't quite
> as straight-forward as I thought at first.

Thanks for that confirmation.  Here's what I'm thinking of doing:

	External interrupts are already masked in the MSR by hardware when
	the exception is taken.  The first level exception handler also
	ensures proper interrupt stack nesting.

	Find out which is the highest hardware priority active interrupt
	source.  Raise the IPL to the IPL of this interrupt, and mask all
	interrupt sources with the same or lower IPL.

	Enable external interrupts in the MSR.

	Run the appropriate interrupt handler.  While running the handler,
	we may accept another higher-IPL interrupt if it occurs.

	Disable external interrupts in the MSR.

	Restore the IPL to what it was before we raised it.  Unmask hardware
	interrupt sources appropriately.  Check for any pending software
	interrupts:

		For each software interrupt source (in order of priority),
		if pending and not masked by IPL:

			Raise the IPL to the level of this interrupt.

			Enable external interrupts in the MSR.

			Run the appropriate handler.  We can be interrupted
			by any higher IPL interrupt (hard or soft) while the
			handler is running.

			Disable external interrupts in the MSR	

		Loop over the software interrupts until no more are pending
		and unmasked.

	Return to the first level handler which will restore the stack.  The
	hardware will enable external interrupts as we leave the first-level
	handler.

Similar but simpler code will be used for the decrementer interrupt.  The
last half or so of the code above forms the splx() function, which is called
by the decrementer interrupt and throughout the kernel to restore the IPL
after a critical section.

Note that in this method, interrupts are deferred in hardware, rather than
in software.  This should give lower latency.  This method also allows
software interrupt handlers to pre-empt one another, according to their IPL.

> Sorry for any confusion.

Not at all.  Thanks again for looking at the code and confirming my read of
it.

Regards,

David Querbach
Real-Time Systems Inc.