Why kernel code/thread executing in interrupt context cannot sleep?

前端 未结 11 1595
余生分开走
余生分开走 2020-11-30 17:20

I am reading following article by Robert Love

http://www.linuxjournal.com/article/6916

that says

\"...Let\'s discuss the fact that work queues run i

相关标签:
11条回答
  • 2020-11-30 17:48

    I think it's a design idea.

    Sure, you can design a system that you can sleep in interrupt, but except to make to the system hard to comprehend and complicated(many many situation you have to take into account), that's does not help anything. So from a design view, declare interrupt handler as can not sleep is very clear and easy to implement.


    From Robert Love (a kernel hacker): http://permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791

    You cannot sleep in an interrupt handler because interrupts do not have a backing process context, and thus there is nothing to reschedule back into. In other words, interrupt handlers are not associated with a task, so there is nothing to "put to sleep" and (more importantly) "nothing to wake up". They must run atomically.

    This is not unlike other operating systems. In most operating systems, interrupts are not threaded. Bottom halves often are, however.

    The reason the page fault handler can sleep is that it is invoked only by code that is running in process context. Because the kernel's own memory is not pagable, only user-space memory accesses can result in a page fault. Thus, only a few certain places (such as calls to copy_{to,from}_user()) can cause a page fault within the kernel. Those places must all be made by code that can sleep (i.e., process context, no locks, et cetera).

    0 讨论(0)
  • 2020-11-30 17:49

    Because the thread switching infrastructure is unusable at that point. When servicing an interrupt, only stuff of higher priority can execute - See the Intel Software Developer's Manual on interrupt, task and processor priority. If you did allow another thread to execute (which you imply in your question that it would be easy to do), you wouldn't be able to let it do anything - if it caused a page fault, you'd have to use services in the kernel that are unusable while the interrupt is being serviced (see below for why).

    Typically, your only goal in an interrupt routine is to get the device to stop interrupting and queue something at a lower interrupt level (in unix this is typically a non-interrupt level, but for Windows, it's dispatch, apc or passive level) to do the heavy lifting where you have access to more features of the kernel/os. See - Implementing a handler.

    It's a property of how O/S's have to work, not something inherent in Linux. An interrupt routine can execute at any point so the state of what you interrupted is inconsistent. If you interrupted the thread scheduling code, its state is inconsistent so you can't be sure you can "sleep" and switch threads. Even if you protect the thread switching code from being interrupted, thread switching is a very high level feature of the O/S and if you protected everything it relies on, an interrupt becomes more of a suggestion than the imperative implied by its name.

    0 讨论(0)
  • 2020-11-30 17:53

    It is just a design/implementation choices in Linux OS. The advantage of this design is simple, but it may not be good for real time OS requirements.

    Other OSes have other designs/implementations.

    For example, in Solaris, the interrupts could have different priorities, that allows most of devices interrupts are invoked in interrupt threads. The interrupt threads allows sleep because each of interrupt threads has separate stack in the context of the thread. The interrupt threads design is good for real time threads which should have higher priorities than interrupts.

    0 讨论(0)
  • 2020-11-30 17:54

    High-level interrupt handlers mask the operations of all lower-priority interrupts, including those of the system timer interrupt. Consequently, the interrupt handler must avoid involving itself in an activity that might cause it to sleep. If the handler sleeps, then the system may hang because the timer is masked and incapable of scheduling the sleeping thread. Does this make sense?

    0 讨论(0)
  • 2020-11-30 17:56

    So what stops the scehduler from putting interrupt context to sleep and taking next schedulable process and passing it the control?

    The problem is that the interrupt context is not a process, and therefore cannot be put to sleep.

    When an interrupt occurs, the processor saves the registers onto the stack and jumps to the start of the interrupt service routine. This means that when the interrupt handler is running, it is running in the context of the process that was executing when the interrupt occurred. The interrupt is executing on that process's stack, and when the interrupt handler completes, that process will resume executing.

    If you tried to sleep or block inside an interrupt handler, you would wind up not only stopping the interrupt handler, but also the process it interrupted. This could be dangerous, as the interrupt handler has no way of knowing what the interrupted process was doing, or even if it is safe for that process to be suspended.

    A simple scenario where things could go wrong would be a deadlock between the interrupt handler and the process it interrupts.

    1. Process1 enters kernel mode.
    2. Process1 acquires LockA.
    3. Interrupt occurs.
    4. ISR starts executing using Process1's stack.
    5. ISR tries to acquire LockA.
    6. ISR calls sleep to wait for LockA to be released.

    At this point, you have a deadlock. Process1 can't resume execution until the ISR is done with its stack. But the ISR is blocked waiting for Process1 to release LockA.

    0 讨论(0)
  • 2020-11-30 17:56

    If a higher-level interrupt routine gets to the point where the next thing it must do has to happen after a period of time, then it needs to put a request into the timer queue, asking that another interrupt routine be run (at lower priority level) some time later.

    When that interrupt routine runs, it would then raise priority level back to the level of the original interrupt routine, and continue execution. This has the same effect as a sleep.

    0 讨论(0)
提交回复
热议问题