Page 1 of 1
irq handlin: should I disable interrupts or not?
Posted: Sat Feb 12, 2022 8:54 pm
by ITchimp
in most of the OS tutorial, the interrupt is disabled by the interrupt handler. I read somewhere that you can format IDT descriptor so that interrupt is disabled automatically... also I read in "understanding linux kernel" that irq can be nested .. can someone help me understand each of these situation with more details that I am trying to get
Re: irq handlin: should I disable interrupts or not?
Posted: Sun Feb 13, 2022 12:24 am
by Octocontrabass
ITchimp wrote:in most of the OS tutorial, the interrupt is disabled by the interrupt handler. I read somewhere that you can format IDT descriptor so that interrupt is disabled automatically...
If you use CLI at the start of your interrupt handler, you could still receive another interrupt after the CPU jumps to the start of the handler but before the CLI instruction runs. This can cause problems if your OS is not prepared to handle a nested interrupt like that.
You should use an interrupt gate if you want to disable interrupts at the start of your interrupt handler.
(You may also see tutorials that use STI before IRET. There is no need for STI before IRET, because IRET will restore the interrupt flag from the stack.)
ITchimp wrote:also I read in "understanding linux kernel" that irq can be nested ..
Modern Linux kernels don't really do nested interrupts anymore. Too many interrupts nesting can overflow the stack.
Re: irq handlin: should I disable interrupts or not?
Posted: Sun Feb 13, 2022 12:32 am
by nullplan
When an interrupt occurs, the CPU will only take it if the interrupt flag is set. In the IDT, you can set the "type" value of your IDT entries to either "trap gate" or "interrupt gate", with the difference being that the latter will automatically disable the IF, and the former will leave it unchanged. What that means in detail depends on your interrupt handling code.
I would suggest using interrupt gates exclusively, then in the interrupt handler finish the work of switching to kernel mode, then determine if enough stack is left over to handle another interrupt right now, and conditionally set the IF. This way, nothing can interrupt the work to switch to kernel mode and interrupts can still nest if need be. And there is no way an interrupt storm can overrun your stack. If you used a trap gate, and then something weird happened and the same interrupt was called constantly, with a trap gate you have no way to disable the interrupt before the stack is overrun.
That said, Linux has switched to threaded interrupt handlers a while ago. How they work is, when the interrupt handler is registered, a thread is started, that in an infinite loop will wait on a semaphore, then execute the interrupt handler. When the actual interrupt arrives, the actual interrupt handler does nothing more than look up the semaphore and post it. Also, the hardware interrupt handler will mask the interrupt in the interrupt controller, and the handler thread will unmask it again after running the handler function.
This might seem needlessly complicated. I mean, take reading the ISA keyboard controller, for instance. That used to be INT -> read keyboard port -> EOI -> IRET, and now it is INT -> mask -> EOI -> sem_post -> IRET -> read keyboard port -> unmask -> sem_wait. But the advantage is that this way, the run time of interrupt handlers gets under control of the scheduler. When handling interrupts directly, the handler code will run at a time when the hardware wants, not when the kernel wants. The kernel has no control to run anything else. But with the threaded model, the run time of all runnable threads can be managed perfectly. I never get tired of talking about that time I misconfigured a Linux kernel so that a certain interrupt condition was always given. And except for some weirdness with timers, you would never know. The system remained perfectly usable. With the direct interrupt handler model, the system would have appeared to lock up entirely when the kernel gains control.
Re: irq handlin: should I disable interrupts or not?
Posted: Sun Feb 13, 2022 3:41 am
by klange
I started doing threaded handlers for my network drivers, and now my virtio input drivers use them as well. It's all still a bit of a mess, nothing nearly as fancy or well-put-together as what Linux is doing, but it did solve a lot of headaches.
Re: irq handlin: should I disable interrupts or not?
Posted: Wed Feb 16, 2022 4:20 am
by ITchimp
Accoring to "understanding the linux kernel", the linux irq model has top half and bottom half, the top half will quickly execute, after which the irq will turn. The real work, stored in tasklet and message queue, will be executed in bottom half, is that you meant by the threaded interrupt handling model? For keyboard input it might be ok, what if there are heavy incoming data stream, would the scheduler take care of these situation so that the incoming data can be handled properly?
nullplan wrote:When an interrupt occurs, the CPU will only take it if the interrupt flag is set. In the IDT, you can set the "type" value of your IDT entries to either "trap gate" or "interrupt gate", with the difference being that the latter will automatically disable the IF, and the former will leave it unchanged. What that means in detail depends on your interrupt handling code.
I would suggest using interrupt gates exclusively, then in the interrupt handler finish the work of switching to kernel mode, then determine if enough stack is left over to handle another interrupt right now, and conditionally set the IF. This way, nothing can interrupt the work to switch to kernel mode and interrupts can still nest if need be. And there is no way an interrupt storm can overrun your stack. If you used a trap gate, and then something weird happened and the same interrupt was called constantly, with a trap gate you have no way to disable the interrupt before the stack is overrun.
That said, Linux has switched to threaded interrupt handlers a while ago. How they work is, when the interrupt handler is registered, a thread is started, that in an infinite loop will wait on a semaphore, then execute the interrupt handler. When the actual interrupt arrives, the actual interrupt handler does nothing more than look up the semaphore and post it. Also, the hardware interrupt handler will mask the interrupt in the interrupt controller, and the handler thread will unmask it again after running the handler function.
This might seem needlessly complicated. I mean, take reading the ISA keyboard controller, for instance. That used to be INT -> read keyboard port -> EOI -> IRET, and now it is INT -> mask -> EOI -> sem_post -> IRET -> read keyboard port -> unmask -> sem_wait. But the advantage is that this way, the run time of interrupt handlers gets under control of the scheduler. When handling interrupts directly, the handler code will run at a time when the hardware wants, not when the kernel wants. The kernel has no control to run anything else. But with the threaded model, the run time of all runnable threads can be managed perfectly. I never get tired of talking about that time I misconfigured a Linux kernel so that a certain interrupt condition was always given. And except for some weirdness with timers, you would never know. The system remained perfectly usable. With the direct interrupt handler model, the system would have appeared to lock up entirely when the kernel gains control.
Re: irq handlin: should I disable interrupts or not?
Posted: Wed Feb 16, 2022 9:59 am
by rdos
ITchimp wrote:Accoring to "understanding the linux kernel", the linux irq model has top half and bottom half, the top half will quickly execute, after which the irq will turn. The real work, stored in tasklet and message queue, will be executed in bottom half, is that you meant by the threaded interrupt handling model? For keyboard input it might be ok, what if there are heavy incoming data stream, would the scheduler take care of these situation so that the incoming data can be handled properly?
Generally speaking, heavy input streams should have memory based schedules and the IRQs just notifies that the queues are updated and won't occur each time something new happens. USB adapters can typically be handled this way, and so can network adapters. Slower USB adapters can even by handled by polling the device at regular intervals. I use this for UHCI and OHCI, particularly because some of these won't have working IRQs anyway.
I don't like the top/bottom half concept that both Linux and Windows use. It's pretty debug hostile.
In my concept, I register interrupt handlers (which can be nested). The registered handler will typically clear the interrupt condition and signal a server thread. The registered handler will always run with interrupts enabled. The registered handler is a normal procedure and will exit with ret, not iret. It will be called from the apic or pic driver through prolog and epilog code that is created dynamically. The IRQ will not be masked, and before the IRQ exits with iret it does an EOI. A server thread will handle the memory based schedule for complex devices. For simple devices, like the keyboard, I put the key codes directly in the keyboard buffer in the registered handler. Same with serial communication handlers. The only issue with that is that the buffers must be synchronized with spinlocks.
Re: irq handlin: should I disable interrupts or not?
Posted: Wed Feb 16, 2022 6:00 pm
by ITchimp
Nullplan, I need your teaching!
Re: irq handlin: should I disable interrupts or not?
Posted: Wed Feb 16, 2022 6:55 pm
by Ethin
ITchimp wrote:Nullplan, I need your teaching!
You do realize that this kind of behavior is unbecoming of you, right? I like the enthusiasm to learn, but everyone here is a volunteer, and we help when we have time. If Nullplan hasn't replied yet, posting repeatedly isn't going to make them reply any faster. Its just going to annoy everyone. You should be willing to learn from everyone here, not just Nullplan. Our answers may not directly answer your queries, but you should accept that and be willing to ask more questions if you don't understand something. You can never ask too many questions, after all, even if we may give you very abstract answers. But you should also be willing to work things out for yourself. We're not going to hold your hand while you develop your OS, you know; we expect you to learn on your own and be willing to figure things out on your own.
Re: irq handlin: should I disable interrupts or not?
Posted: Thu Feb 17, 2022 1:35 am
by ITchimp
I m sorry that you felt that way, the reply from people other than nullplan and Octo seems quite tangential and hard to understand
Re: irq handlin: should I disable interrupts or not?
Posted: Thu Feb 17, 2022 10:24 am
by Ethin
ITchimp wrote:I m sorry that you felt that way, the reply from people other than nullplan and Octo seems quite tangential and hard to understand
Understandable, but remember that asking questions doesn't hurt anyone. If someone says something that you don't understand, don't hesitate to ask for more information. But try not to demand, either. We'll give you advice and assistance with code and stuff but at the end of the day, the ideas we put forth are our ways of doing things, and I, for one, always encourage you to try your own way of doing something, if only for the learning opportunity.
Re: irq handlin: should I disable interrupts or not?
Posted: Thu Feb 17, 2022 11:56 am
by nullplan
ITchimp wrote:Nullplan, I need your teaching!
I am very sorry for your condition. Nobody deserves that. I am just a monkey at a typewriter, trying to make sense of the world around me, and I rarely have a working plan in my head, hence the nickname.
ITchimp wrote:Accoring to "understanding the linux kernel", the linux irq model has top half and bottom half, the top half will quickly execute, after which the irq will turn. The real work, stored in tasklet and message queue, will be executed in bottom half, is that you meant by the threaded interrupt handling model? For keyboard input it might be ok, what if there are heavy incoming data stream, would the scheduler take care of these situation so that the incoming data can be handled properly?
Ah, so that is what a bottom half is. I had been wondering. I read the term before and didn't really know what it meant, but did not know how to research. Not that I cared that much.
As for what I meant by "threaded interrupt handling model", that is literally what the code called it when I read it. The drivers don't know about that, BTW, they just request an interrupt to be handled with a certain function. But the function that connects function pointer and interrupt spawns a new kernel thread that, as I described, waits on a semaphore, then executes the function by function pointer. There is a bit more complexity in there, allowing for oneshot interrupts (when you want to deregister the interrupt handler after it runs once), and also facilitating interrupt sharing, a blight no longer cursing our computers so much since the advent of the X2APIC and the MSI, but still a possibility.
For performance, there is no way to know but to measure it. But honestly, if it wasn't fast enough for typical applications that are not entirely stupid (e.g. trying to run a 10GbE adapter on a 486 computer), Linux would probably use a different model. I wouldn't worry about performance until I'd finished building the system. Make it work first, then make it work fast. This is not difficult to do.