why cannot sleep in the ISR

here is a maillist discussing the problem about why cannot sleep in the ISR from linux newbie.
it is worth reading throughout if you do not clear about this question.

~~~~~~~~~~~~~~~~~



发件人: Learning Linux
发送时间: 2007-05-14 14:40:54
收件人: [email protected]; [email protected]
抄送: [email protected]
主题: Why can't we sleep in an ISR?

I have a very basic doubt here ... what makes it impossible to sleep
in an ISR? I mean, I know that the kernel preemption is disabled and
the kernel will panic, but I could not understand why?

TIA,

====================
Learning Linux wrote:
> I have a very basic doubt here ... what makes it impossible to sleep
> in an ISR? I mean, I know that the kernel preemption is disabled and
> the kernel will panic, but I could not understand why?

The impossibility to sleep comes as a natural consequence of the fact 
that ISRs have to be fast.

An ISR has to be fast in order to allow other system tasks to happen. 
Otherwise it will do a lot of work (like busy waiting) and any other 
interrupts will fail to get handled. That would completely render the 
system unusable.

On the other hand, when you sleep in a given context, the scheduler is 
invoked. That means that the ISR routine would be replaced by a process 
from the scheduler's queue(s). But how would you ever know to reschedule 
the ISR? After all, it is asynchronous.

This is why ISRs (top halves) and tasklets/softirqs (bottom halves) are 
said to be running in interrupt context; processes are said to be 
running in process context.

Interrupt context has very strict rules like being unable to sleep or do 
a large amount of work (this will render the system unable and, quite 
likely, a panic would occur).

Hope this helps. You should be read Robert Love's excellent "Linux 
Kernel Development 2nd Edition". It is quite readable and has a pleasant 
way of showing you the basic kernel concepts. Chapter 6 is concerned 
with interrupts and interrupt handling routines (ISRs).

Razvan

============================

Because the interrupt which you are serving in the ISR has been masked to avoid preemption( true for maskable inetrrupts ).Any locks you are holding in ISR are now with you solely. So, if you try to sleep you take the locks you untill you are rescheduled and complete. This may lead to a deadlock for the lock resource. 
Thus to avoid this, kernel developers disable preemption and also on every schedule check if you are *in_interrupt*, if you are, you are probably doing something really bad.So its better to panic in such case.

This is my naive understanding.
Please CMIIW.

========================

> Because the interrupt which you are serving in the
> ISR has been masked to avoid preemption(
> true for maskable inetrrupts ).Any locks you are holding in ISR are now with
> you solely. So, if you try to sleep you take the locks you untill you are
> rescheduled and complete. This may lead to
> a deadlock for the lock resource.

Ok, but how about an ISR, that does not take any locks? Why can't we
sleep in SUCH an ISR?

AFAIK, taking a lock disables kernel preemption, and hence it is not
allowed to sleep. So I think my question would boil down to why is
sleeping not allowed when the kernel preemption is disabled.

LL

========================================

>
> On the other hand, when you sleep in a given context, the scheduler is
> invoked. That means that the ISR routine would be replaced by a process
> from the scheduler's queue(s). But how would you ever know to reschedule
> the ISR? After all, it is asynchronous.

Uh, this is what I have my doubt about. Yes, the scheduler may try to
replace the current process (already interrupted by the ISR) with
another process.

So, what is the problem with that? Could you please elaborate on the
part "how would you ever know to reschedule the ISR? After all, it is
asynchronous"?

======================================
>>
>> On the other hand, when you sleep in a given context, the scheduler is
>> invoked. That means that the ISR routine would be replaced by a process
>> from the scheduler's queue(s). But how would you ever know to reschedule
>> the ISR? After all, it is asynchronous.

> Uh, this is what I have my doubt about. Yes, the scheduler may try to
> replace the current process (already interrupted by the ISR) with
> another process.

> So, what is the problem with that? Could you please elaborate on the
> part "how would you ever know to reschedule the ISR? After all, it is
> asynchronous"?

Well, the ISR code has to be resumed at some point doesn't it? How would 
you know how to "get back" at executing it? There's no ISR scheduling 
queue, as there is no process. An ISR can interrupt any given process 
(that's what I meant by asynchronous).

And even if that weren't a problem you would still have to deal with 
another problem: if an important interrupt (like the timer interrupt) 
would sleep and would (somehow) manage to get rescheduled, you would 
lose any notion of time within that system; it will inconsistent, and it 
will break all other subsystems (like scheduling) (the process time 
slice would lose its meaning)

Razvan

===========================
> > I have a very basic doubt here ... what makes it impossible to sleep
> > in an ISR? I mean, I know that the kernel preemption is disabled and
> > the kernel will panic, but I could not understand why? 
>
> Because the interrupt which you are serving in the
> ISR has been masked to avoid preemption(
> true for maskable inetrrupts ).Any locks you are holding in ISR are now with
> you solely. So, if you try to sleep you take the locks you untill you are 
> rescheduled and complete. This may lead to
> a deadlock for the lock resource.

Ok, but how about an ISR, that does not take any locks? Why can't we
sleep in SUCH an ISR?

Adding extra complexity is to be refrained from, because such ISRs are very few IMHO.   
Moreover on a SMP system why wouldn't you need a lock? preemption is disabled only on the local processor i guess. CMIIW



AFAIK, taking a lock disables kernel preemption, and hence it is not
allowed to sleep. So I think my question would boil down to why is
sleeping not allowed when the kernel preemption is disabled.

Who will preempt you, in this case? i.e to sleep? No one, you will complete and therefore you should be really fast in doing it. 
Becasue you have just disabled kernel preemption. In other words ISR is not like any other process waiting to run, it is a special kernel control path which is special because of the reasons you have given. 
There is no task struct for your interrupt, no accounting as such AFAIR and etc etc.

It runs in current process's context, isnt it? 
HTH

~psr
=====================================

> Well, the ISR code has to be resumed at some point doesn't it? How would
> you know how to "get back" at executing it? There's no ISR scheduling
> queue, as there is no process. An ISR can interrupt any given process
> (that's what I meant by asynchronous).

Yes. The ISR can interrupt any process. But the scheduler is totally
unaware of it (CMIIW). As far as scheduler is concerned, it thinks
that the processor is still executing the code of the process that ISR
interrupted. In fact, all the time ISR executes is deducted from the
timeslice of the process that was interrupted.

Assuming the simple case of 8KB stacks (ISRs share the process stack).
So the scheduler can still perform a context switch saving and
restoring the save of the process it THINKS is currently executing
(The PC will actually point to an address in ISR) and later on restore
from where it left?

==============================
>
> > AFAIK, taking a lock disables kernel preemption, and hence it is not
> > allowed to sleep. So I think my question would boil down to why is
> > sleeping not allowed when the kernel preemption is disabled.
>
> Who will preempt you, in this case? i.e to sleep? No one,
> you will complete and therefore you should
> be really fast in doing it.

Ok, lets forget about ISRs and interrupts. Let us say I have a kernel
thread running in process context, and it takes a lock (thus disables
preemption) which is used ONLY by this thread. Now it WANTS to sleep
for some time, while holding a lock.

There surely ARE a lot of runnable processes in the system, who can
run. Now technically sleeping, what stops this process from sleeping?
Why can't this process sleep safely?

Uh, just to clarify, I totally understand that this is not allowed and
will be a bad design. But I just want to understand that in terms of
kernel code, what STOPS this process from going to sleep?


=============================

> >> On the other hand, when you sleep in a given context, the scheduler is
> >> invoked. That means that the ISR routine would be replaced by a process
> >> from the scheduler's queue(s). But how would you ever know to reschedule 
> >> the ISR? After all, it is asynchronous.
> >
> > Uh, this is what I have my doubt about. Yes, the scheduler may try to
> > replace the current process (already interrupted by the ISR) with 
> > another process.
> >
> > So, what is the problem with that? Could you please elaborate on the
> > part "how would you ever know to reschedule the ISR? After all, it is
> > asynchronous"? 
>
> Well, the ISR code has to be resumed at some point doesn't it? How would
> you know how to "get back" at executing it? There's no ISR scheduling
> queue, as there is no process. An ISR can interrupt any given process 
> (that's what I meant by asynchronous).

Yes. The ISR can interrupt any process. But the scheduler is totally
unaware of it (CMIIW). As far as scheduler is concerned, it thinks
that the processor is still executing the code of the process that ISR 
interrupted. In fact, all the time ISR executes is deducted from the
timeslice of the process that was interrupted.


===========================
Learning Linux wrote:
> I have a very basic doubt here ... what makes it impossible to sleep
> in an ISR? I mean, I know that the kernel preemption is disabled and
> the kernel will panic, but I could not understand why?
First: an ISR is meant to be very quick. It is supposed to do only a
minimum of work needed to service the interrupt, then exit.
This is important, as other interrupts might be blocked during your ISR.
Sleeping is out of question, even a long-running loop in no-no.

Second: You don't ever need to sleep in an ISR anyway.
Complicated work that might take time or might need to sleep
is not supposed to be in an ISR. If you think you have a need,
tell us what you're up to and hopefully someone will explain
how do do things properly.

When an interrupt happens that needs complicated servicing, the
ISR don't do the whole job. It just acknowledges the interrupt,
perhaps does a few things with the device in question, then it
exits. It leaves the rest of the work for a bottom half or kernel
thread or something like that. Kernel threads may sleep . . .

Helge Hafting

=================================
My understanding is as follows.

Whenever the kernel code sleeps, it means the latest process running
in user space will have to wait for the event on which the kernel code
sleeps.

It makes sense for an exception handler to sleep because an exception
handler always serves the latest process running in user space. So a
process can complain nothing for it having to wait for the event on
which the exception handler in its own context sleeps.

It makes no sense for an ISR to sleep because an ISR does not
necessarily serve the latest process (that is, the interrupted
process). It makes no sense having a process wait for the event having
nothing to do with it.

I could be wrong, so please correct me if the understanding is not right.


Dong Feng<[email protected]>

=======================

On 5/14/07, Learning Linux <[email protected]> wrote:
> Ok, but how about an ISR, that does not take any locks? Why can't we
> sleep in SUCH an ISR?
> LL
> -

The killer reason why you can't sleep in an interrupt is because an
interrupt is not associated with any context in the first place. What
is a context, then? It is the state information for a process. This
includes the kernel and userspace stack pointers, the register set,
and the page tables for that process. The scheduler has access to all
this information, to preempt one process and run another. Contrary to
this, an interrupt, depending on the version of your kernel and arch,
uses a separate irq stack or the kernel stack of the interrupted
process. An irq is not a context but merely a temporary execution to
be concluded asap.

Hope this helps,
Bahadir

=======================================
I agree that the reason an interrupt can not sleep is because an
interrupt is not associated with any context. But I do not agree that
it is specifically because the scheduler can not *resume* the context.

In early version, the ISR always borrow the stack of the currently
running process, so if the kernel design had allowed ISR sleep, it
would automatically be able to implement the context switch naturally.
But ISR sleep has been forbidden from the very beginning.

The reason why kernel design does not allow ISR sleep is because a
process should not be forced to wait for a event that irrelative to
itself. When an exception handler sleep, the event it sleeps on is
always in some sense related to the process incurring that exception.
But if an ISR was allowed to sleep, the event it sleeps on would have
nothing to do with the process being interrupted.

So my understanding is, the forbidden of ISR sleep is not because of
the difficulty to resume context, but because a process should not
wait for irrelative event.

Dong Feng<[email protected]>
================================

On 5/14/07, Bahadir Balban <[email protected]> wrote:
On 5/14/07, Learning Linux <[email protected]> wrote:
> Ok, but how about an ISR, that does not take any locks? Why can't we
> sleep in SUCH an ISR? 
> LL
> -

The killer reason why you can't sleep in an interrupt is because an
interrupt is not associated with any context in the first place.

good enough, but i have a query regarding this then. 
On a 8K kernel stack system, doesn't interrupts share the stack associated with the current process which was interrupted? 
Doesn't interrupt steals the CPU slice time allocated to the running process to run? 
Doesn't it run in current process's context ? 

What am i missing here? 

Thanks 
~psr
=====================================
>
> good enough, but i have a query regarding this then.
> On a 8K kernel stack system, doesn't interrupts share the stack associated
> with the current process which was interrupted?

Yes, I think so.

> Doesn't interrupt steals the CPU slice time allocated to the running process
> to run?

I don't think so but I am not sure.

> Doesn't it run in current process's context ?
>

No. I think the concept of process context is a higher-level logical
concept. Though the interrupt share stack with the interrupted
process, in my opinion it logically does not share the context with
the process.

> What am i missing here?
>
> Thanks
> ~psr
>


But I do not see the exact relationship between your specific queries
and the original question. Could you elaborate?


Dong Feng<[email protected]>

===================================

On 5/15/07, Dong Feng <[email protected]> wrote:
>
> good enough, but i have a query regarding this then.
> On a 8K kernel stack system, doesn't interrupts share the stack associated
> with the current process which was interrupted?

Yes, I think so. 

Yes it does.
> Doesn't interrupt steals the CPU slice time allocated to the running process
> to run?

I don't think so but I am not sure.

Aliter, i think so.How can an interrupt's execution time go unaccounted then? 
I guess it does not, only the current processes running time is accounted for.
Thoughts?



> Doesn't it run in current process's context ?
>

No. I think the concept of process context is a higher-level logical
concept. Though the interrupt share stack with the interrupted
process, in my opinion it logically does not share the context with 
the process.

Yes, you are right as i can infer. thats why ISRs are special kernel control paths.
But the poster asked, why can't we make ISRs to share context with the interrupted process if 
it not holding any locks? This is rather a desing issues IMO rather than imlementation, isnt it? 

I guess even if it is possible, it would over complicate the handler code. Better trying to keep it simple i guess. Please CMIIW 



[snip]

But I do not see the exact relationship between your specific queries
and the original question. Could you elaborate?

My query here was related to your previous reply.Just wanted to pit some doubts as raised by the orirignal poster.That's it.

Thank you
~psr 

================================

> >
> > I don't think so but I am not sure.
>
> Aliter, i think so.How can an interrupt's execution time go
> unaccounted then?
> I guess it does not, only the current processes running
> time is accounted for.
> Thoughts?
>

The interrupt handler's execution time will definitely defer the
execution of the process, but I think it does not steal the process's
time slice (the time_slice field not subtracted).

> > > Doesn't it run in current process's context ?
> > >
> >
> > No. I think the concept of process context is a higher-level logical
> > concept. Though the interrupt share stack with the interrupted
> > process, in my opinion it logically does not share the context with
> > the process.
>
> Yes, you are right as i can infer. thats why ISRs
> are special kernel control paths.
> But the poster asked, why can't we make ISRs to
> share context with the interrupted process
> if
> it not holding any locks? This is rather a desing issues
> IMO rather than imlementation, isnt it?
>
> I guess even if it is possible, it would over complicate the handler code.
> Better trying to keep it simple i guess. Please CMIIW

My understanding is, the ISR is in different context from the process
because of the definition of term *context*. In my opinion, to say two
code pieces running in the same context means that two pieces of code
has some logical relationship to meet a common objective. That's why I
said *context* is a higher-level logical concept. It's not a concept
defined in the level of hardware or code implementation, but instead
in the level of logical. I think, by its definition, it makes no sense
to say an ISR share context with the process interrupted by it because
an ISR just randomly interrupts a process, with no logical
relationship.


Dong Feng<[email protected]>
========================
On 5/15/07, Dong Feng <[email protected] > wrote:
> >
> > I don't think so but I am not sure.
>
> Aliter, i think so.How can an interrupt's execution time go
> unaccounted then?
> I guess it does not, only the current processes running 
> time is accounted for.
> Thoughts?
>

The interrupt handler's execution time will definitely defer the
execution of the process, but I think it does not steal the process's
time slice (the time_slice field not subtracted). 

Ok, if i accept this, how does that explains this- 

Following code snippet is from main schedule() function[kernel 2.6.20.1] - 

now = sched_clock();
if(likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) { 
       run_time = now - prev->timestamp;
       /* blah blah */
} else
            run_time = NS_MAX_SLEEP_AVG;

Now, AFAIK runtime = now - prev->timestamp; will get you a value which ( prev->timestamp is *stamped* during previous switching of the tasks) is difference of this previous stamp and now value. 
Assuming before this schedule() an interrupt was served, then where did the time spent in ISR accounting is adjusted? I guess this is the code, where it is checking for a *possible* runtime to overshoot its stipulated NS_MAX_SLEEP_AVG and resetting this. Isn't it? 
And exactly why would that happen? 
Perhaps because the process was about to expire its slice when somebody barged in and stole its share and also overshot the stipulated time(may be very less though). 

Can you help me in clearing this? 



> > > Doesn't it run in current process's context ?
> > >
> >
> > No. I think the concept of process context is a higher-level logical
> > concept. Though the interrupt share stack with the interrupted 
> > process, in my opinion it logically does not share the context with
> > the process.
>
> Yes, you are right as i can infer. thats why ISRs
> are special kernel control paths.
> But the poster asked, why can't we make ISRs to 
> share context with the interrupted process
> if
> it not holding any locks? This is rather a desing issues
> IMO rather than imlementation, isnt it?
>
> I guess even if it is possible, it would over complicate the handler code. 
> Better trying to keep it simple i guess. Please CMIIW

My understanding is, the ISR is in different context from the process
because of the definition of term *context*. In my opinion, to say two
code pieces running in the same context means that two pieces of code 
has some logical relationship to meet a common objective. That's why I
said *context* is a higher-level logical concept. It's not a concept
defined in the level of hardware or code implementation, but instead 
in the level of logical. I think, by its definition, it makes no sense
to say an ISR share context with the process interrupted by it because
an ISR just randomly interrupts a process, with no logical
relationship. 

Right agreed. 

Thanks 
~psr

====================

> The interrupt handler's execution time will definitely defer the
> execution of the process, but I think it does not steal the process's
> time slice (the time_slice field not subtracted).

It will definitely be substracted from the process's time slice.
Because the timeslice is substracted in timer interrupt, and does not
differenciate if the process is executing ISR or not.

====================
Yes, you are right in this regard. An interrupt handler does steal the
time slice from the interrupted process.

So now I think it is considered an acceptable deviation in calculating
the process run time as well as determine process scheduling because
an ISR should take very short time to return, in part as a consequence
of the rule that ISR should not sleep.


Dong Feng<[email protected]>
====================================



On Tue, 15 May 2007 pradeep singh wrote :
>On 5/14/07, Bahadir Balban <[email protected]> wrote:
>>
>>On 5/14/07, Learning Linux <[email protected]> wrote:
>> > Ok, but how about an ISR, that does not take any locks? Why can't we
>> > sleep in SUCH an ISR?
>> > LL
>> > -
>>
>>The killer reason why you can't sleep in an interrupt is because an
>>interrupt is not associated with any context in the first place.
>
>
>good enough, but i have a query regarding this then.
>On a 8K kernel stack system, doesn't interrupts share the stack associated
>with the current process which was interrupted?
Yes, you are right.
>Doesn't interrupt steals the CPU slice time allocated to the running process
>to run?
Yes
>Doesn't it run in current process's context ?
You got it worng here. It runs on behalf of the process, but in the current process's context. 
For interrupts we have a dirrerent context altogether.
>
>What am i missing here?
There are two different contexts of execution
Process context
Interrupt context
>
>Thanks
>~psr
>
Thanks,
-Rohit
=====================================


On 15 May 2007 09:34:23 -0000, rohit hooda <[email protected]> wrote:



On Tue, 15 May 2007 pradeep singh wrote :
>On 5/14/07, Bahadir Balban < [email protected]> wrote:
>>
>>On 5/14/07, Learning Linux <[email protected] > wrote:
>> > Ok, but how about an ISR, that does not take any locks? Why can't we
>> > sleep in SUCH an ISR?
>> > LL
>> > -
>> 
>>The killer reason why you can't sleep in an interrupt is because an
>>interrupt is not associated with any context in the first place.
>
>
>good enough, but i have a query regarding this then. 
>On a 8K kernel stack system, doesn't interrupts share the stack associated
>with the current process which was interrupted?
Yes, you are right.
>Doesn't interrupt steals the CPU slice time allocated to the running process 
>to run?
Yes
>Doesn't it run in current process's context ?
You got it worng here. It runs on behalf of the process, but in the current process's context. 
For interrupts we have a dirrerent context altogether.

Ok, that explains a bit.
how will you define an interrupt context? 

Thanks 
~psr 

=========================
Dong Feng wrote:
>> Doesn't it run in current process's context ?
>>

> No. I think the concept of process context is a higher-level logical
> concept. Though the interrupt share stack with the interrupted
> process, in my opinion it logically does not share the context with
> the process.

No, the term context here has a specific meaning. It refers to those 
things which flow from the current pointer, including the virtual memory 
space, file descriptor table, current uid, and so forth. Because the 
current pointer is not changed on entry to an ISR, the ISR is executing 
in the context of the interrupted process, and thus uses that process' 
virtual memory, etc.

===================================

2007/5/16, Phillip Susi <[email protected]>:
> Dong Feng wrote:
> >> Doesn't it run in current process's context ?
> >>
> >
> > No. I think the concept of process context is a higher-level logical
> > concept. Though the interrupt share stack with the interrupted
> > process, in my opinion it logically does not share the context with
> > the process.
>
> No, the term context here has a specific meaning. It refers to those
> things which flow from the current pointer, including the virtual memory
> space, file descriptor table, current uid, and so forth. Because the
> current pointer is not changed on entry to an ISR, the ISR is executing
> in the context of the interrupted process, and thus uses that process'
> virtual memory, etc.
>

If what you say were true, then an ISR would be running in the same
context as the interrupted process. But please check any article or
book, it will say ISR running in different context from any process.
So ISR is considered in its own context, although it shares a lot of
things with the interrupted process. I would only say *context* is a
higher-level logical concept.


Dong Feng<[email protected]>

==========================

Dong Feng wrote:
> If what you say were true, then an ISR would be running in the same
> context as the interrupted process. 

Yes, and it is, as others have said in this thread, which is a good 
reason why ISRs can't sleep.

> But please check any article or
> book, it will say ISR running in different context from any process.
> So ISR is considered in its own context, although it shares a lot of
> things with the interrupted process. I would only say *context* is a
> higher-level logical concept.

Depends on which book or article you are reading I suppose. The 
generally accepted and often used thought is that ISRs technically are 
running in the context of the interrupted process, but because that 
context is unknown and therefore should not be used, it is often said 
that they run in no context, or outside of any context. Sometimes 
people then assume that because they run outside of any ( particular ) 
process context, they must be in their own context, but this is a mistake.


Phillip Susi<[email protected]>

==================================


======================
Hi ...
> I have a very basic doubt here ... what makes it impossible to sleep
> in an ISR? I mean, I know that the kernel preemption is disabled and
> the kernel will panic, but I could not understand why?
Sorry, I reply back to the top "level". I try to read related chapters 
on Understanding The Linux kernel 3rd edition. I found something (page 
144, Chapter 4 "Interrupts and Exceptions")...I quote them here:
The price to pay allowing nested kernel control paths is that an 
interrupt handler must never block, that is, no process switch can take 
place until an interrupt handler is running. In fact, all the data 
needed to resume a nested kernel control path is stored in the Kernel 
Mode stack, which is tightly bound to the current process.

I hope it can shed a light for you regarding your confusion.

regards,

Mulyadi

====================================
OK. I think the gap between you and me is the definition of term
*context*. If you go to Linux Kernel Development, 2nd Edition (ISBN
0-672-32720-1), Page 6, then you will read the following:

.... in Linux, ... each processor is doing one of three things at any
given moment:

1. In kernel-space, in process context, ...
2. In kernel-space, in interrupt context, not associated with a process, ...
3. In user-space ...

This list is inclusive. ...


Maybe you prefer other terminology system, but I do like the above
definition given by Robert Love. So maybe in your system *context*
mean something at hardware level and you say ISR is in process
context, but I think it is more like a logical level and agree with
Rovert's definition.

And in hardware level, Robert's *context* definition also mean
something specific, that I started to be aware of. That is, *in the
same context* means a kernel-code is triggered by a user-space code.
*in different context* means a kernel-code is triggered by an external
interrupt source other than a user-space code.

Context has nothing to do with whether an ISR borrow any data
structure of a process, instead, its something logical or related to
causality.

你可能感兴趣的:(why cannot sleep in the ISR)