Yesterday on IRC I asked whether in SMP systems, there's only one instance of a specific IRQ handler at any point in time. Travis kindly replied that
So I can happily code external interrupt handlers with no need of making each one concurrency-safe with respect to itself. Searching the IO-apic sheet and Intel manuals though, I found that when a local apic receives an End-of-Interrupt (EOI), it informs the IO-apics about this EOI only in case of level interrupts. Upon receiving an EOI for edge-triggered interrupt, the local apic does not inform the IO-apic of this event. Quoting from Intel's chapter:it's the responsibility of the interrupt controller(s) to not trigger the same irq simultaneously on different cpus, at least global, hardware interrupts.
And quoting another paragraph from the same chapter which says it more explicitly:The act of writing to the EOI register causes the local APIC to delete the interrupt from its ISR queue and (for level-triggered interrupts) send a message on the bus indicating that the interrupt handling has been completed.
So in the time between we ACK a hardware device and send an EOI, how does the IOAPIC know that this edge-triggered handler is still in execution, and avoids forwarding the device next interrupt to another core?Upon acceptance of an interrupt into the IRR, the corresponding TMR [Trigger Mode Register] bit is cleared for edge-triggered interrupts and set for level-triggered interrupts. If a TMR bit is set when an EOI cycle for its corresponding interrupt vector is generated, an EOI message is sent to all I/O APICs.
Thanks a lot!
Edit: per forum rules, avoid using colored text.