Depending on your hardware configuration, there may actually be multiple hardware sources associated with an interrupt. This issue is a function of your specific hardware and bus type. This characteristic (plus good programming style) mandates that your ISR ensure that the hardware associated with it actually caused the interrupt.
Most PIC (Programmable Interrupt Controller) chips can be programmed to respond to interrupts in either an edge-sensitive or level-sensitive manner. Depending on this programming, interrupts may be sharable.
For example:
In the above scenario, if the PIC is operating in a level-sensitive mode, the IRQ is considered active whenever it's high. In this configuration, while the second assertion (step 2) doesn't itself cause a new interrupt, the interrupt is still considered active even when the original cause of the interrupt is removed (step 3). Not until the last assertion is cleared (step 4) will the interrupt be considered inactive.
In edge-triggered mode, the interrupt is noticed only once, at step 1. Only when the interrupt line is cleared, and then reasserted, does the PIC consider another interrupt to have occurred.
QNX Neutrino allows ISR handlers to be stacked, meaning that multiple ISRs can be associated with one particular IRQ. The impact of this is that each handler in the chain must look at its associated hardware and determine if it caused the interrupt. This works reliably in a level-sensitive environment, but not an edge-triggered environment.
To illustrate this, consider the case where two hardware devices are sharing an interrupt. We'll call these devices HW-A and HW-B. Two ISR routines are attached to one interrupt source (via the InterruptAttach() or InterruptAttachEvent() call), in sequence (i.e., ISR-A is attached first in the chain, ISR-B second).
Now, suppose HW-B asserts the interrupt line first. QNX Neutrino detects the interrupt and dispatches the two handlers in order. ISR-A runs first and decides (correctly) that its hardware didn't cause the interrupt. Then ISR-B runs and decides (correctly) that its hardware did cause the interrupt; it then starts servicing the interrupt. But before ISR-B clears the source of the interrupt, suppose HW-A asserts an interrupt; what happens depends on the type of IRQ:
Since ISR-A clears the source of the interrupt (and ISR-B doesn't do anything, because its associated hardware doesn't require servicing), everything functions as expected.