In article <d8hj6g$t49$1@inn.qnx.com>, Wojtek_L@yahoo.ca says…
“ed1k” <> ed1k@fake.address> > wrote in message
news:> MPG.1d143180f3fd3df79896ce@inn.qnx.com> …
In article <d8c1ip$rm0$> 1@inn.qnx.com> >, > Wojtek_L@yahoo.ca > says…
[…]
Don’t Windows and Linux allow threads to mask an interrupt in a way
similar
to InterruptMask() in QNX? If they do, then they have the same problem.
If you’re asking about user land, I believe no. Though I’m unsure, never
been there for long time.
No, I was asking about driverland… My point was that the problem can
happen in any OS that makes it possible for a driver to mask an interrupt
and then get pre-empted before unmasking it, which I imagine is a wider
category than the OSes that have a function similar to
InterruptAttachEvent().
Well, then it’s rather complex question. As you know, every OS provide
its own model for drivers and interrupt handling. Usually these models
do not project on the underlying hardware (PIC) so straight as QNX model
does. Windows NT doesn’t have any function that impilicitly masks
particular interrupt line, AFAIK. What NT driver can do it’s to rise its
IRQL (IRQ level) effectively disabling all hardware IRQ below that IRQL.
In NT, when ISR is running it might be preempted by any higher level
ISR, and it may schedule DPC for futher processing. DPCs will run in
FIFO order at IRQL below any hardware interrupt but above any thread
in system (it is actually software interrupt or exeption in MS
terminology). DPC receives/sends data from/to memory buffer/device, but
it’s not the last instance for all data processing or finishing IRP,
rest of job will be done at lower IRQL where we can talk about threads.
There is synchronisation function which allows to change IRQL and so
called “critical sections” to avoid simultaneosly accessing to the
hardware - I don’t know how they are close to masking interrupts in the
PIC… They deal with spinlock for particular IRQ, I guess it’s property
of the kernel. In other words, if NT driver for some reason rises its
IRQL (masking all IRQLs of that level and below) it can be pre-empted
only by higher level IRQ. There is no possibility for discussed problem,
though I am not discussing real-time capabilities of NT or acceptance of
such design for RTOS. NT is not RTOS.
There are disable_irq() and enable_irq() functions in Linux kernel which
seems to be close to InterruptMask/InterruptUnmask() in QNX. Though it’s
not common practice in Linux kernel, you probably may write a
minimalistic ISR that masks irq line and schedules tasklet for futher
processing. Tasklet can’t be pre-empted by any thread. So, situation
similar to InterruptAttachEvent() is impossible. But I agree, if some
kernel thread working on behalf of some user’s process calls disable_irq
() it can be pre-empted by high priority thread, therefore unmasking
latency is at the mercy of that high priority thread. Though I have to
say pre-emption in linux kernel showed up only recently and it is not
always working
Additionally they usually use cli/sti() around
critical sections - no interrupts, no pre-emption
Linux is not RTOS,
is it?
OK, the problem is that you’re relying on a thread to unmask the interrupt,
and that the priorities of threads in your system have been assigned in a
way that interferes with the unmasking. It’s not very surprising that you
can mess up a realtime system by assigning priorities incorrectly, is it…
No, it’s not a surprise. But opening up a box with RTOS, installing
thing on a computer and using only components from box with their
“default” priorities may I hope I have RTOS and it’s not already messed
up?
Sure; but you’re not saying that no program can possibly have a good reason
to ever call InterruptMask() from a thread, are you?
I am not sure
Probably not, I’m not saying. Thought I can’t think of
a good example.
BTW, disable_irq(int no) in linux waits for currently executing ISR
handler if any to complete. QNX documentation doen’t mention such
behaviour, so I assume InterruptMask() doesn’t wait. So, it’s a really
bad wrapper for critical section… and I honestly would be thankful for
example of good usage of InterruptMask() in a thread.
If a thread in a driver calls InterruptMask() (presumably, for a good
reason), then it has to deal with exactly the same issues as
InterruptAttachEvent() creates. It doesn’t make a big difference whether
the interrupt was masked by the thread or by an ISR, and it doesn’t matter
whether the ISR was the private one that InterruptAttachEvent() uses or a
user-written one that calls InterruptMask() and then returns an event. As
long as it’s a thread’s responsibility to unmask it, the unmasking is
affected by any higher-priority threads and may affect any drivers using the
same interrupt, and that can cause problems on systems that don’t give you
enough control over thread priorities and interrupt assignments. On the
other hand, it may happen to be the most efficient way to handle some
hardware on systems where you can fine tune all the details. My point is
that talking about it as the problem were specific to InterruptAttachEvent()
may give some people the impression that if their driver doesn’t use
InterruptAttachEvent(), then their driver is guaranteed not to have the
problem.
Ok, I got you. On the other hand, knowing about the problem it is
possible to use InterruptAttachEvent() or InterruptMask/InterruptUnmask
and avoid damage of the problem.
Eduard.