In article <d8aaaj$jlm$1@inn.qnx.com>, evanh@clear.net.nz says…
Armin Steinhoff wrote:
Evan Hillas wrote:
Armin Steinhoff wrote:
This is not a ‘conflict’ … interrupt sharing is absolutely normal
with PCI.
It is, however, a conflict at the driver level purely because of
internal QSSL decision.
Not at ‘driver level’. It is done at the ISR level and that is more or
less independ from the driver.
What is ‘driver level’ and what is ISR level? I always thought the ISR
is a part of driver (of course, if device serviced by the driver
requires some interrupt handling). How can it be independent?
What?! I just finished explaining, clearly I thought, how it is the software design of the “other” shared driver that is causing the sharing problem.
Here is my few cents to this discussion or why shared interrupts in QNX
is worse than shared interrupts in Linux or Windows (at least while QNX
driver uses InterruptAttachEvent() call to install “default” ISR).
Windows domain.
When ISR running at DIRQL decides it needs some more
processing, but it might be done at the lower priority
level, it put deffered procedure call (DPC) into queue.
DPC will be executed later with DISPATCH_LEVEL priority
that is above any user’s thread in a system, but below
hardware generated interrupts.
Priority levels (excursus to windows terms):
HIGHEST_LEVEL -bus errors and machine checks
…
DIRQLs -hardware interrupt requests
DISPATH_LEVEL -scheduler and DPC execution
…
PASSIVE_LEVEL -normal thread execution level
Linux domain.
If ISR decides it needs some more processing, but it
might be done later when interrupts acknowledged and
enabled, it put tasklet into queue to run. (Old kernels used
bottom halves (BH) to do deffered interrupt processing, apparently
BH mechanism in modern Linux kernels is a wrapper to tasklets, just
backward compatibility). It’s pretty close to Windows’ DPC (from view
of priorities and execution context).
QNX domain.
If ISR decides it needs some more processing that could be
done later when interrupts acknowledged and enabled, it returns
event to the thread which is blocked waiting this event. Nice. It’s
easy to understand and easy to program. Now take a look at
InterruptAttachEvent(). It puts “default” ISR handler which masks
interrupt line and returns event to waiting thread. Fine. The
problem lays in a priority of that waiting thread. It may be a way
too low and this thread would be preempted by more “high priority”
task effectively leaving hardware interrupt line deaf to the
requests. And this is a difference from two models described above.
Actually, it’s easy to reduce the gap by boosting priority of
the interrupt waiting thread to max and return it back to normal
as soon as the thread issues UnmaskInterrupt(). I don’t know why this
is not default behaviour for InterruptAttachEvent(), but it can
be done programmatically for now. However, none of QNX standard
drivers do that, AFAIK. Therefore, some QNX standard driver might
be a dangerous neighbour to share interrupt line with.
Boosting interrupt hadling thread’s priority by passing argument
to driver may not be a good solution, because it looks more
logically to unmask interrupt ASAP and do the rest of job processing
the data with lower priority (although if rumours are true and
network drivers unmask interrupt after all data have been processed
this really doesn’t make difference, it’s just bad design).
Also, I don’t know if there is a queue for events returned by ISR. (I
did some experiments with QNX 6.0 and I believe there was not queue, but
I’m not sure). It also may make a difference.
Cheers,
Eduard.
The drivers that seem to be the biggest abuser of the flawed method are the network drivers.
Evan