hardware interrupt IRQ conflict

Mario Charest wrote:

Correction, This prevents all other driver on that IRQ and of IRQ with lower
priority to get their due. That means when InterruptAttachEvent attach is
used, IRQ of lower priority get a lower priority then that of the thread
serving the event, that seems to defeat the purpose of IRQ which is typicaly
be of higher priority the processes/threads.

I understand your point about an ISR losing it’s priority over all interrupt handler threads (IHT) and it is roughly true but it’s just a subset of the design flaw. The flaw only exists for those devices on the same IRQ.

You do have one bit wrong, though. The IRQ priorities inside the PIC are only there for resolving which IRQ is serviced first if there is more than one in contention. In our situation where an IRQ is masked while a drivers IHT does it’s thing then this IRQ is not in contention for service so all other IRQ’s are free to continue being serviced.


Evan

Evan Hillas wrote:

Rennie Allen wrote:

I make the rules

It is my application and I want to be able to control every aspect of it.
If the work is done in the ISR instead of an IHT I have very limited (and
completely non-portable) control of how it gets scheduled. If the
work is
done in an IHT (and I have command line priority parameters for stock
drivers) then I have complete (and portable) control of how everything
gets scheduled.


You’re miss understanding what is being asked for. The work is still
done in the same places just that the driver masks/unmasks the device
instead of the IRQ. That’s all the difference is.

I don’t think I am misunderstanding at all. If a 2 stage priority scheme
(i.e. 1st stage does minimum amount of work - which still might be pretty
substantial - to disable device IRQ, then immediately unmasks the IRQ,
then 2nd stage does whatever else is necessary) is required, then simply
program the driver like this.

I have no problem with saying that QNX drivers should choose between IA
and IAE as appropriate (i.e. if the the board can be serviced with nothing
more than a write to an register then I don’t care if it uses IA); but
saying that IAE is a defective concept is just plain wrong.

When I worked at QNX as neutrino was first being designed, I suggested
that IAE be able to take a register address to read from/write to (perhaps
with a mask and value) to clear the device IRQ), but this idea was
(correctly) shot down with the argument that if the device requires nothing
but a single register read/write, then IA is hardly a programming burden,
and introducing a third API for such a trivial piece of “sugar” would be
redundant (since IAE would still be needed for devices that have more
demanding work to clear the source).

Rennie

Evan Hillas wrote:

Rennie Allen wrote:

IAE better not disappear from device drivers ! IAE is the only way to
truly have control over all priorities (including the interrupt



The priorities don’t disappear with an ISR, the drivers that want to do
the work with a prioritised thread can still get sent the same events
using InterruptAttach() as InterruptAttachEvent() can send.

You misunderstand. ISRs are not schedulable; therefore if the hardware
in question is burdensome to clear, that work can not be prioritized.

Rennie

In article <d8mqgg$nsl$1@inn.qnx.com>, dagibbs@qnx.com says…

The “if the thread doesn’t do this” bit is referring to the ThreadCtl(),
and, yes, there is definitely a cut & paste error there – it’s in
the InterruptLock() page, too. I’ll issue a PR to have it fixed.

Hm… I just checked some other Interrupt*() function – it seems every
function says (for example, InterruptDetach()):

Before calling either of these functions, the thread must request I/O
privity by calling:

ThreadCtl( _NTO_TCTL_IO, 0 );
If the thread doesn’t do this, it might SIGSEGV when it calls
InterruptUnlock().

It looks like InterruptUnlock() is a check point either or not a thread
did call ThreadCtl(). Is it the same error? I would expect SIGSEGV just
at the time of calling any Interrupt*() function if I didn’t call
ThreadCtl(). I always assumed that and now I finally have read something
different :slight_smile:

Ok, I hope I was right in my assumptions. Thanks for PR.

Cheers,
Eduard.

In article <d8n3no$152$2@inn.qnx.com>, dagibbs@qnx.com says…

They talk directly to the PIC, so if the interrupt level is masked,
it is masked for all CPUs in an SMP situation. But, there is a
potential race condition:

PIC raises interrupt X, CPU1 starts handling it
Thread on CPU2 masks interrupt X
handler for interrupt X runs on CPU1 while thread on CPU2 thinks
it is safe to touch hardware.

I don’t know if there is any code to check whether or not this
could happen.

Thanks, That’s exactly what I meant. I don’t know either, though must be
spinlocks. On the same note – is InterruptDetach() SMP safe?
Documentation says this call don’t block. So, scenario:

APIC raises interrupt x, CPUn starts handling the interrupt chain
attached to IRQx.
Thread on CPUm decides it’s time to detach interrupt and exit. At the
time CPUn wants to execute ISR, there is no ISR in memory anymore.

Eduard.

In article <42AF6F0C.6070509@csical.com>, rallen@csical.com says…

I don’t think I am misunderstanding at all. If a 2 stage priority scheme
(i.e. 1st stage does minimum amount of work - which still might be pretty
substantial - to disable device IRQ, then immediately unmasks the IRQ,
then 2nd stage does whatever else is necessary) is required, then simply
program the driver like this.

I have no problem with saying that QNX drivers should choose between IA
and IAE as appropriate (i.e. if the the board can be serviced with nothing
more than a write to an register then I don’t care if it uses IA); but
saying that IAE is a defective concept is just plain wrong.

I don’t think IAE should be removed. Just accent must be put on
drawbacks of this concepts (surprisingly, these are listed in
documentation) not benefits. Main drawback is that IHT works on behalf
hardware interrupt with a low priority of ordinal thread. I think the
fact that command line options for IHT priority added just recently in
QNX drivers is a proof of a wide ignorance, maybe including QSS staff :slight_smile:

When I worked at QNX as neutrino was first being designed, I suggested
that IAE be able to take a register address to read from/write to (perhaps
with a mask and value) to clear the device IRQ), but this idea was
(correctly) shot down with the argument that if the device requires nothing
but a single register read/write, then IA is hardly a programming burden,
and introducing a third API for such a trivial piece of “sugar” would be
redundant (since IAE would still be needed for devices that have more
demanding work to clear the source).

Was not around some idea like this at that time (just currious, if it
was why it was shot down):

void CriticalSection(void){
//this code is executed at MAX_PRIORITY-1;
//do required minimum to de-assert IRQ
//…
//exit from this function implies InterruptUnmask()
//just for symmetry -
//we didn’t call IM() explicitly with IAE()
//why we should unmask?.
}

void* IHT(void *data){
//init and preparing
//…

//only one type of events allowed for this technique
//flags doesn’t make much sense either
InterruptAttachEvent(int intr);
//…

while(1){
InterruptWaitEvent(CriticalSection)
//here is code to do rest of job after deasserting IRQ


};
};


If one needs something more sophisticated, use IA() as the only choice.

Eduard.

Rennie Allen wrote:

Evan Hillas wrote:

Rennie Allen wrote:

IAE better not disappear from device drivers ! IAE is the only way to
truly have control over all priorities (including the interrupt


The priorities don’t disappear with an ISR, the drivers that want to
do the work with a prioritised thread can still get sent the same
events using InterruptAttach() as InterruptAttachEvent() can send.


You misunderstand. ISRs are not schedulable; therefore if the hardware
in question is burdensome to clear, that work can not be prioritized.

That work can still be done in the IHT, the ISR just has to mask the device. Both parts can exist in the same driver.


Evan

Okay, but sharing is still being excluded by the QSS drivers. This should not be the default behaviour. Maybe it should be a “paid for” Performance Tech Kit.


Evan

Nice ideas but prolly worse than IA() because as soon as the thread’s priority changes there is a good chance there will be a context switch anyway. So having an ISR will incur less overhead not to mention you are putting ISR-like restrictions on that method too.

The two methods already available are fine, just the question of the default driver behaviour is my concern.


Evan

In article <d8ov34$eij$1@inn.qnx.com>, evanh@clear.net.nz says…

Nice ideas but prolly worse than IA() because as soon as the thread’s priority changes there is a good chance there will be a context switch anyway.

And what? That is exactly what I want most of the time in RTOS. I
cleaned hardware and now I want to calculate CRC over received data or
whatever. Why don’t be pre-empted?


So having an ISR will incur less overhead not to mention you are putting ISR-like restrictions on that method too.

I am not putting ISR-like restriction. In ISR you can’t do many, in a
thread, even if it’s running at very high priority, you still can. You
can put printf’s in CriticalSection, for example, if you want to debug.

I forgot to mention, the idea may cover current state of IAE()

InterruptWaitEvent(NULL);
//there is no critical code, there is no priority boost,
//so you must call InterruptUnmask() explicitly
//…
//and you’re warned!

The two methods already available are fine,

They are almost perfect. I like QNX6 because of these easy yet powerfull
methods. No hassle to use them in comparison to Windows NT, for example.

just the question of the default driver behaviour is my concern.

My question was “if I were walking this road again”. I do not expect any
changes (regarding interrupt handling) in QNX API. I do not expect much
from the drivers side. You can assign priority now, in 6.3 “priority=N”

Eduard.

ed1k wrote:

In article <d8ov34$eij$> 1@inn.qnx.com> >, > evanh@clear.net.nz > says…

Nice ideas but prolly worse than IA() because as soon as the thread’s priority changes there is a good chance there will be a context switch anyway.


And what? That is exactly what I want most of the time in RTOS. I
cleaned hardware and now I want to calculate CRC over received data or
whatever. Why don’t be pre-empted?

ISR + IHT covers that and incurs minimal context switching in the process.

About the only thing that would be tighter execution would be a special ISR that has no access to thread space and can only be configured at init time and can only send the intr event.


Evan

In article <MPG.1d196c142c97db529896d3@inn.qnx.com>,
ed1k <ed1k@fake.address> wrote:

Thanks, That’s exactly what I meant. I don’t know either, though must be
spinlocks. On the same note – is InterruptDetach() SMP safe?
Documentation says this call don’t block. So, scenario:

APIC raises interrupt x, CPUn starts handling the interrupt chain
attached to IRQx.
Thread on CPUm decides it’s time to detach interrupt and exit. At the
time CPUn wants to execute ISR, there is no ISR in memory anymore.

The call doesn’t block in the sense that another thread is scheduled
to be run, but it does wait until there are no interrupts being handled
before removing the attachment to avoid the above scenario.

\

Brian Stecher (bstecher@qnx.com) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M 1W8

ed1k <ed1k@fake.address> wrote:

In article <d8mqgg$nsl$> 1@inn.qnx.com> >, > dagibbs@qnx.com > says…
The “if the thread doesn’t do this” bit is referring to the ThreadCtl(),
and, yes, there is definitely a cut & paste error there – it’s in
the InterruptLock() page, too. I’ll issue a PR to have it fixed.

Hm… I just checked some other Interrupt*() function – it seems every
function says (for example, InterruptDetach()):

Before calling either of these functions, the thread must request I/O
privity by calling:

ThreadCtl( _NTO_TCTL_IO, 0 );
If the thread doesn’t do this, it might SIGSEGV when it calls
InterruptUnlock().

It looks like InterruptUnlock() is a check point either or not a thread
did call ThreadCtl(). Is it the same error?

No, this is a cut&paste error in the docs. In each case, they should
say ÿmight sigsegv when calling .

That is, for InterruptLock(), it should say “might SIGSEGV when it
calls InterruptLock()”.

I would expect SIGSEGV just
at the time of calling any Interrupt*() function if I didn’t call
ThreadCtl().

Yes, that is correct.

I always assumed that and now I finally have read something
different > :slight_smile:

Cut & paste error. Gotta love 'em.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

ed1k <ed1k@fake.address> wrote:

In article <d8n3no$152$> 2@inn.qnx.com> >, > dagibbs@qnx.com > says…
They talk directly to the PIC, so if the interrupt level is masked,
it is masked for all CPUs in an SMP situation. But, there is a
potential race condition:

PIC raises interrupt X, CPU1 starts handling it
Thread on CPU2 masks interrupt X
handler for interrupt X runs on CPU1 while thread on CPU2 thinks
it is safe to touch hardware.

I don’t know if there is any code to check whether or not this
could happen.

Checked with kernel person – there is no code to prevent this.

Thanks, That’s exactly what I meant. I don’t know either, though must be
spinlocks.

Is difficult to use spinlocks to handle this – for a spinlock to work
safely, you need interrupts disabled. (Otherwise you can get into
deadlocks.) And, of course, you can’t disable, acquire spin, then
InterruptMask() cause the InterruptMask() will re-enable interrupts
(it’s a kernel call).

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Evan Hillas wrote:

The two methods already available are fine, just the question of the
default driver behaviour is my concern.

The fact that they use IAE, or the fact that they don’t have 2
(configurable) IHT processing priorities ? I can agree with the latter.
The former implies more interrupt latency than the OS should add.

Rennie

Evan Hillas wrote:

Okay, but sharing is still being excluded by the QSS drivers. This
should not be the default behaviour. Maybe it should be a “paid for”
Performance Tech Kit.

I certainly don’t dispute that certain drivers may have problems, but
this is a specific implementation issue, not a core OS design issue.

Perhaps you have a list of drivers that InterruptMask() longer than
the hardware requires ?

Rennie

In article <d8pjf9$sl6$1@inn.qnx.com>, dagibbs@qnx.com says…

I don’t know if there is any code to check whether or not this
could happen.

Checked with kernel person – there is no code to prevent this.

So, it could happen in SMP environment. Good to know, thanks. Do you (or
kernel person rather) have any plans to make InterruptMask() SMP safe?

Thanks, That’s exactly what I meant. I don’t know either, though must be
spinlocks.

Is difficult to use spinlocks to handle this – for a spinlock to work

Sorry, I meant there must be spinlocks in ukernel for every interrupt
level. Otherwise I hardly can imagine how Neutrino interrupt dispatcher
works. I didn’t mean usage of user space spinlock to workaround the
problem - it’s a definitive deadlock :slight_smile:

I think it is possible to have a single SMP-safe InterruptMask() call in
QNX (not two as it’s in linux), because ukernel can probably distinguish
where the call came from (by meaning of CPU ring level or somehow
differently). So, thread would be if not blocked in meaning scheduled
off of execution, but waiting while ISR chain processed. ISR masking its
level of interrupt should not wait anything, of course. Special case
would be if someone decides to mask some IRQ level from within ISR for
different level…

Thank you,
Eduard.

safely, you need interrupts disabled. (Otherwise you can get into
deadlocks.) And, of course, you can’t disable, acquire spin, then
InterruptMask() cause the InterruptMask() will re-enable interrupts
(it’s a kernel call).

-David

Rennie Allen wrote:

Evan Hillas wrote:

Rennie Allen wrote:

IAE better not disappear from device drivers ! IAE is the only way to
truly have control over all priorities (including the interrupt




The priorities don’t disappear with an ISR, the drivers that want to
do the work with a prioritised thread can still get sent the same
events using InterruptAttach() as InterruptAttachEvent() can send.


You misunderstand. ISRs are not schedulable; therefore if the hardware
in question is burdensome to clear, that work can not be prioritized.

Some kind of prioritization happens with the order of InterruptAttach()
calls.

Just to avoid all of this probems … the kernel should be handle the
interrupt issues like XEN :slight_smile:

http://www.cl.cam.ac.uk/Research/SRG/netos/xen/

–Armin

Rennie Allen wrote:

Evan Hillas wrote:

Okay, but sharing is still being excluded by the QSS drivers. This
should not be the default behaviour. Maybe it should be a “paid for”
Performance Tech Kit.


I certainly don’t dispute that certain drivers may have problems, but
this is a specific implementation issue, not a core OS design issue.

If you read just my comments you will see that while I don’t think much of IAE() I’m really just complaining about drivers using it recklessly.


Perhaps you have a list of drivers that InterruptMask() longer than
the hardware requires ?

That’s an easy answer. All the drivers that ever expect to be sharable and make use of IRQ masking as an interrupt servicing mechanism.

It seems like most of em but I don’t have the interrupt handling sources of them all to confirm this impression.


Evan

Rennie Allen wrote:

Evan Hillas wrote:

The two methods already available are fine, just the question of the
default driver behaviour is my concern.


The fact that they use IAE, or the fact that they don’t have 2
(configurable) IHT processing priorities ? I can agree with the latter.
The former implies more interrupt latency than the OS should add.

By default I mean the lack of support for sharing.


Evan