Linked by Hadrien Grasland on Sun 27th Feb 2011 12:06 UTC
Hardware, Embedded Systems This is a situation where I need the help of you OSnews readers who are experienced with low-level development on ARM, SPARC, PowerPC, MIPS, and other hardware architectures we have on computers nowadays. The issue is that I'm currently designing the part of my hobby kernel which takes care of interrupts. Although I mostly work on x86 at the moment, I'd like to keep this code portable to other hardware architectures in the future. To do that, I have to know how interrupt handling works on as much HW architectures as possible.
Thread beginning with comment 464408
To view parent comment, click here.
To read all comments associated with this story, please click here.
RE[2]: General Notes
by Brendan on Tue 1st Mar 2011 10:31 UTC in reply to "RE: General Notes"
Brendan
Member since:
2005-11-16

Hi,

"For example, if an IRQ occurs you might ask an ethernet card driver if it was responsible, and if that driver says the ethernet card was responsible for the IRQ then you wouldn't bother asking any other device drivers (to avoid unnecessary overhead).


Nope. Multiple devices can interrupt simultaneously. If you do it this way, you have to pay the interrupt overhead twice if that occurs (the first time when you stopped asking at the Ethernet driver, but the interrupt was still asserted; the second time as sson as the Ethernet driver handled its interrupt).
"

I'm used to micro-kernels, where drivers run in user-space and the IRQ overhead itself (and therefore the potential risk of a second IRQ) is nothing compared to the cost of a (potentially unnecessary) task switch.

For monolithic kernels where performance is considered far more important than protection/security; the fastest way is to trash the kernel's code with random data as soon as any IRQ occurs. It's guaranteed to be faster than waiting for any number of arbitrary drivers to trash the kernel... :-)

- Brendan

Reply Parent Score: 2

RE[3]: General Notes
by Anachronda on Tue 1st Mar 2011 22:52 in reply to "RE[2]: General Notes"
Anachronda Member since:
2007-04-18

I'm used to micro-kernels, where drivers run in user-space and the IRQ overhead itself (and therefore the potential risk of a second IRQ) is nothing compared to the cost of a (potentially unnecessary) task switch.


What happens if two devices request an interrupt on the same IRQ at the same time? I imagine it goes something like this:

- ISR takes interrupt, finds first driver attached to this interrupt, and sends a message to it. Interrupt is disabled until driver gets a chance to run.
- Microkernel eventually schedules driver, which processes interrupt request and re-enables interrupts from the slot.
- ISR takes interrupt from second device, which has been plaintively waving its hand the whole time, finds appropriate driver, and sense message to it. Interrupt is disabled until driver gets a chance to run.
- Microkernel eventually schedules driver, which processes interrupt request and re-enables interrupts from slot.

For monolithic kernels where performance is considered far more important than protection/security; the fastest way is to trash the kernel's code with random data as soon as any IRQ occurs. It's guaranteed to be faster than waiting for any number of arbitrary drivers to trash the kernel... :-)


Have you been looking at my code?

Reply Parent Score: 1

RE[4]: General Notes
by Brendan on Wed 2nd Mar 2011 00:33 in reply to "RE[3]: General Notes"
Brendan Member since:
2005-11-16

Hi,

"I'm used to micro-kernels, where drivers run in user-space and the IRQ overhead itself (and therefore the potential risk of a second IRQ) is nothing compared to the cost of a (potentially unnecessary) task switch.


What happens if two devices request an interrupt on the same IRQ at the same time? I imagine it goes something like this:
"

The case you started with is 2 devices generating the same IRQ at same time and the first driver is one of them, with "early bail-out":
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- kernel does EOI, APIC/PIC sends second IRQ
- ISR sends message to first driver
- first driver handles message, tells kernel "not me"
- ISR sends message to second driver
- second driver handles message, tells kernel "it was me"
- kernel does EOI

That's probably 3 task switches. Without "early bail-out" you get this:
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- ISR sends message to second driver
- second driver handles message, tells kernel "it was me"
- kernel does EOI

That's 2 task switches, which is better for this specific case. What if the first device generates an IRQ again before this is finished? In that case you get this (with early bail-out):

- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- kernel does EOI, APIC/PIC sends second IRQ
- ISR sends message to first driver
- first driver handles message, tells kernel "not me"
- ISR sends message to second driver
- second driver handles message, tells kernel "it was me"
- kernel does EOI, APIC/PIC sends third IRQ
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- kernel does EOI

Now there's 4 task switches. Without early bail-out:
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- ISR sends message to second driver
- second driver handles message, tells kernel "it was me"
- kernel does EOI, APIC/PIC sends third IRQ
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- ISR sends message to second driver
- second driver handles message, tells kernel "not me"
- kernel does EOI

That's also 4 task switches, so early bail-out didn't hurt but didn't help either.

What if there's only one IRQ? Here's how that goes with early bail-out:
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- kernel does EOI

That's 1 task switch for early bail-out. Without early bail-out:
- ISR sends message to first driver
- first driver handles message, tells kernel "it was me"
- ISR sends message to second driver
- second driver handles message, tells kernel "not me"
- kernel does EOI

That's 2 task switches - almost twice as bad as "with early bail-out".

What if there's only one IRQ, but it's for the second device and not the first? I won't go through that, but it's 2 task switches in both cases.

Now, how likely are each of these cases? The most common case is the "one IRQ to first device" case, where early bail-out is twice as good. You can guarantee that this is more likely than the "one IRQ to second device" case (by sorting the order drivers are told about the IRQ).

The interesting part is trying to figure out which conditions early bail-out causes a "net performance loss". The cases where early bail-out don't help or hurt don't matter much, which leaves us with 2 cases to consider. If the "2 IRQs at the same time" case (with 3 task switches instead of 2) happens as often as the "1 IRQ for the first device" case (with 1 task switch instead of 2); then you get "3 + 1 vs. 2 + 2" or 4 task switches vs. 4 task switches. That's the break even point.

Basically, early bail-out only causes a net performance loss when the "2 IRQs at the same time" case is more common than the "one IRQ for first device" case. That's fairly unlikely.

Have you been looking at my code?


:-)

- Brendan

Reply Parent Score: 2