All of lore.kernel.org
 help / color / mirror / Atom feed
* interrupt context
       [not found] <CA+bLfK5FPqFvU2xy7xKdV4LkAvmY6GAPFrB-4UBzn-cOunQ6Xg@mail.gmail.com>
@ 2012-10-05  8:51 ` Iain Fraser
  2012-10-05  9:32   ` Borislav Petkov
  2012-10-05 13:27   ` Theodore Ts'o
  0 siblings, 2 replies; 27+ messages in thread
From: Iain Fraser @ 2012-10-05  8:51 UTC (permalink / raw)
  To: linux-kernel

Hello,

I understand the interrupts and softirq's run in interrupt context (
as opposed to process context ). But what I
don't understand is why you cannot sleep in interrupt context?

What I have read it states that it doesn't have a process to schedule
out. But interrupts use the interrupted processes
kernel stack just like a syscall. So surely it is possible to sleep
using that stack. Understandably It would be unfair on the process
that blocked through no fault of its own.

Also if you are not allowed to sleep / schedule during interrupt
context. Then how does the system timer pre-empt processes by
calling schedule?

I understand there are many reasons why you shouldn't: irq lines being
disabled, quick completion, etc. But I don't understand
why you cannot.

Thanks for the help
Iain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05  8:51 ` interrupt context Iain Fraser
@ 2012-10-05  9:32   ` Borislav Petkov
  2012-10-05 10:20     ` Iain Fraser
  2012-10-05 13:27   ` Theodore Ts'o
  1 sibling, 1 reply; 27+ messages in thread
From: Borislav Petkov @ 2012-10-05  9:32 UTC (permalink / raw)
  To: Iain Fraser; +Cc: linux-kernel

On Fri, Oct 05, 2012 at 09:51:55AM +0100, Iain Fraser wrote:
> Hello,
> 
> I understand the interrupts and softirq's run in interrupt context (
> as opposed to process context ). But what I
> don't understand is why you cannot sleep in interrupt context?
> 
> What I have read it states that it doesn't have a process to schedule
> out. But interrupts use the interrupted processes
> kernel stack just like a syscall. So surely it is possible to sleep
> using that stack. Understandably It would be unfair on the process
> that blocked through no fault of its own.
> 
> Also if you are not allowed to sleep / schedule during interrupt
> context. Then how does the system timer pre-empt processes by
> calling schedule?
> 
> I understand there are many reasons why you shouldn't: irq lines being
> disabled, quick completion, etc. But I don't understand
> why you cannot.

Let's imagine for a second we could sleep in IRQ context and we had some
dummy process entity we can schedule out from.

So, we schedule out and run another process which enters the kernel and
grabs a lock L.

At that exact moment, another IRQ on the same line is raised, we execute
the same IRQ handler which purely coincidentally starts busy-waiting on
the same lock L.

How long do you think we'll be busy waiting in IRQ context on that lock?

:-)

HTH.

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05  9:32   ` Borislav Petkov
@ 2012-10-05 10:20     ` Iain Fraser
  2012-10-05 10:34       ` Borislav Petkov
  0 siblings, 1 reply; 27+ messages in thread
From: Iain Fraser @ 2012-10-05 10:20 UTC (permalink / raw)
  To: Borislav Petkov, Iain Fraser, linux-kernel

Hi,

Thanks for the response. But it appears your example illustrates why its bad
to sleep while you have a lock. Which I understand, what I wanted to know is
why in interrupt context under no circumstances are you allowed to sleep?

Btw I have no intention of doing this, I'm just curious. After
thinking about it further
I'm starting to think its a "design" decision as opposed to a side effect of the
kernel implementation.

If you could answer:

"How can the system timer ( obviously in interrupt context ) call
schedule when it is impossible to sleep/schedule in interrupt context?"

That would help me greatly.

Thanks again
iain

On Fri, Oct 5, 2012 at 10:32 AM, Borislav Petkov <bp@alien8.de> wrote:
> On Fri, Oct 05, 2012 at 09:51:55AM +0100, Iain Fraser wrote:
>> Hello,
>>
>> I understand the interrupts and softirq's run in interrupt context (
>> as opposed to process context ). But what I
>> don't understand is why you cannot sleep in interrupt context?
>>
>> What I have read it states that it doesn't have a process to schedule
>> out. But interrupts use the interrupted processes
>> kernel stack just like a syscall. So surely it is possible to sleep
>> using that stack. Understandably It would be unfair on the process
>> that blocked through no fault of its own.
>>
>> Also if you are not allowed to sleep / schedule during interrupt
>> context. Then how does the system timer pre-empt processes by
>> calling schedule?
>>
>> I understand there are many reasons why you shouldn't: irq lines being
>> disabled, quick completion, etc. But I don't understand
>> why you cannot.
>
> Let's imagine for a second we could sleep in IRQ context and we had some
> dummy process entity we can schedule out from.
>
> So, we schedule out and run another process which enters the kernel and
> grabs a lock L.
>
> At that exact moment, another IRQ on the same line is raised, we execute
> the same IRQ handler which purely coincidentally starts busy-waiting on
> the same lock L.
>
> How long do you think we'll be busy waiting in IRQ context on that lock?
>
> :-)
>
> HTH.
>
> --
> Regards/Gruss,
>     Boris.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05 10:20     ` Iain Fraser
@ 2012-10-05 10:34       ` Borislav Petkov
  0 siblings, 0 replies; 27+ messages in thread
From: Borislav Petkov @ 2012-10-05 10:34 UTC (permalink / raw)
  To: Iain Fraser; +Cc: linux-kernel

On Fri, Oct 05, 2012 at 11:20:20AM +0100, Iain Fraser wrote:
> Hi,
> 
> Thanks for the response. But it appears your example illustrates why its bad
> to sleep while you have a lock. Which I understand, what I wanted to know is
> why in interrupt context under no circumstances are you allowed to sleep?
> 
> Btw I have no intention of doing this, I'm just curious. After
> thinking about it further
> I'm starting to think its a "design" decision as opposed to a side effect of the
> kernel implementation.

There are more examples where sleeping in IRQ context is simply
problematic. So prohibiting sleeping in such contexts turns out to be
the simplest solution concerning code complexity, design, handling, etc.

Btw, you can trigger some yourself by adding sleeping functions in an
IRQ handler used on your system, disable the "sleeping-while-atomic"
warnings and try to run it to see what happens.

> If you could answer:
>
> "How can the system timer ( obviously in interrupt context ) call
> schedule when it is impossible to sleep/schedule in interrupt
> context?"

I think the best way to learn these things is to stare at the code until
you've understood exactly what it does when it does it, so I'll let you
answer that.

And you want to learn because you wouldn't be asking those questions in
the first place. :-)

HTH.

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05  8:51 ` interrupt context Iain Fraser
  2012-10-05  9:32   ` Borislav Petkov
@ 2012-10-05 13:27   ` Theodore Ts'o
  2012-10-05 14:03     ` Iain Fraser
                       ` (2 more replies)
  1 sibling, 3 replies; 27+ messages in thread
From: Theodore Ts'o @ 2012-10-05 13:27 UTC (permalink / raw)
  To: Iain Fraser; +Cc: linux-kernel

On Fri, Oct 05, 2012 at 09:51:55AM +0100, Iain Fraser wrote:
> 
> I understand the interrupts and softirq's run in interrupt context (
> as opposed to process context ). But what I
> don't understand is why you cannot sleep in interrupt context?

Consider what happens with nested locks (and yes, we definitely need
nested locks).  In order to prevent deadlocks, it is critical to have
lock ordering; that is, you always take locks in a certain order.  If
all processes take lock A, and then lock B, etc., then you won't have
a problem where one process as lock A, and tries to get lock B, and
another process has lock B, and tries to take lock A, and they wait
for each other forever.

If a process has a lock when it gets interrupted, the interrupt
handler has no idea what locks may have already been taken.  So if a
process has taken a mutex (or some other sleeping lock) B, and then
the interrupt handler tries to take lock A, that's a perscription for
deadlock.

In addition, you must never sleep while holding a (non-sleeping)
spinlock.  If the interrupt handler has interrupted a process which is
holding a spinlock, then it simply may not sleep without triggering
all sorts of other problems.

> What I have read it states that it doesn't have a process to schedule
> out. But interrupts use the interrupted processes
> kernel stack just like a syscall. So surely it is possible to sleep
> using that stack. Understandably It would be unfair on the process
> that blocked through no fault of its own.
> 
> Also if you are not allowed to sleep / schedule during interrupt
> context. Then how does the system timer pre-empt processes by
> calling schedule?

The system timer sets the "need to reschedule" flag for that
particular process.  Then as the system timer returns from the
interrupt, there is a common code path which is checked on the way out
of any interrupt handler or system call.  This code path checks to see
if the "need to schedule" flag is set, and if so, at that point
instead of returning to the original process, the kernel will simply
return to some other process.

I would suggest that you get a good introductory Linux book, such as
"Linux Kernel Development" by Robert Love.  You might also check out
the kernelnewbies.org website and mailing list, where you are more
likely to get answers to basic introductory questions like this.

Regards,

						- Ted

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05 13:27   ` Theodore Ts'o
@ 2012-10-05 14:03     ` Iain Fraser
  2012-10-05 18:05     ` anish kumar
  2012-10-05 18:15     ` Iain Fraser
  2 siblings, 0 replies; 27+ messages in thread
From: Iain Fraser @ 2012-10-05 14:03 UTC (permalink / raw)
  To: Theodore Ts'o, Iain Fraser, linux-kernel

Thanks for the response Ted. I've actual got that book, in fact it is
the source of this question :) .

I knew it wasn't a "nice" thing to do to the poor process. But your
explanation explains why
its also a dangerous thing so thanks.

Also another problem with async sleeping a process, is that you could
end up causing the idle
thread to sleep. And end up in a scenario where there are no runnable tasks.

Thanks for the help
Iain


On Fri, Oct 5, 2012 at 2:27 PM, Theodore Ts'o <tytso@mit.edu> wrote:
> On Fri, Oct 05, 2012 at 09:51:55AM +0100, Iain Fraser wrote:
>>
>> I understand the interrupts and softirq's run in interrupt context (
>> as opposed to process context ). But what I
>> don't understand is why you cannot sleep in interrupt context?
>
> Consider what happens with nested locks (and yes, we definitely need
> nested locks).  In order to prevent deadlocks, it is critical to have
> lock ordering; that is, you always take locks in a certain order.  If
> all processes take lock A, and then lock B, etc., then you won't have
> a problem where one process as lock A, and tries to get lock B, and
> another process has lock B, and tries to take lock A, and they wait
> for each other forever.
>
> If a process has a lock when it gets interrupted, the interrupt
> handler has no idea what locks may have already been taken.  So if a
> process has taken a mutex (or some other sleeping lock) B, and then
> the interrupt handler tries to take lock A, that's a perscription for
> deadlock.
>
> In addition, you must never sleep while holding a (non-sleeping)
> spinlock.  If the interrupt handler has interrupted a process which is
> holding a spinlock, then it simply may not sleep without triggering
> all sorts of other problems.
>
>> What I have read it states that it doesn't have a process to schedule
>> out. But interrupts use the interrupted processes
>> kernel stack just like a syscall. So surely it is possible to sleep
>> using that stack. Understandably It would be unfair on the process
>> that blocked through no fault of its own.
>>
>> Also if you are not allowed to sleep / schedule during interrupt
>> context. Then how does the system timer pre-empt processes by
>> calling schedule?
>
> The system timer sets the "need to reschedule" flag for that
> particular process.  Then as the system timer returns from the
> interrupt, there is a common code path which is checked on the way out
> of any interrupt handler or system call.  This code path checks to see
> if the "need to schedule" flag is set, and if so, at that point
> instead of returning to the original process, the kernel will simply
> return to some other process.
>
> I would suggest that you get a good introductory Linux book, such as
> "Linux Kernel Development" by Robert Love.  You might also check out
> the kernelnewbies.org website and mailing list, where you are more
> likely to get answers to basic introductory questions like this.
>
> Regards,
>
>                                                 - Ted

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05 13:27   ` Theodore Ts'o
  2012-10-05 14:03     ` Iain Fraser
@ 2012-10-05 18:05     ` anish kumar
  2012-10-05 18:15     ` Iain Fraser
  2 siblings, 0 replies; 27+ messages in thread
From: anish kumar @ 2012-10-05 18:05 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Iain Fraser, linux-kernel

On Fri, 2012-10-05 at 09:27 -0400, Theodore Ts'o wrote:
> On Fri, Oct 05, 2012 at 09:51:55AM +0100, Iain Fraser wrote:
> > 
> > I understand the interrupts and softirq's run in interrupt context (
> > as opposed to process context ). But what I
> > don't understand is why you cannot sleep in interrupt context?
> 
> Consider what happens with nested locks (and yes, we definitely need
> nested locks).  In order to prevent deadlocks, it is critical to have
> lock ordering; that is, you always take locks in a certain order.  If
> all processes take lock A, and then lock B, etc., then you won't have
> a problem where one process as lock A, and tries to get lock B, and
> another process has lock B, and tries to take lock A, and they wait
> for each other forever.
> 
> If a process has a lock when it gets interrupted, the interrupt
> handler has no idea what locks may have already been taken.  So if a
> process has taken a mutex (or some other sleeping lock) B, and then
> the interrupt handler tries to take lock A, that's a perscription for
> deadlock.
> 
> In addition, you must never sleep while holding a (non-sleeping)
> spinlock.  If the interrupt handler has interrupted a process which is
Just to get it right for me.Most of the time spinlock disables the local
core interrupts(or all cores interrupts) and when you call the sleep
function after holding the spinlock the interrupts will be  enabled
again(Am I right?).This is not desired and will have unknown results.
> holding a spinlock, then it simply may not sleep without triggering
> all sorts of other problems.
> 
> > What I have read it states that it doesn't have a process to schedule
> > out. But interrupts use the interrupted processes
> > kernel stack just like a syscall. So surely it is possible to sleep
> > using that stack. Understandably It would be unfair on the process
> > that blocked through no fault of its own.
> > 
> > Also if you are not allowed to sleep / schedule during interrupt
> > context. Then how does the  system timer pre-empt processes by
> > calling schedule?
> 
> The system timer sets the "need to reschedule" flag for that
> particular process.  Then as the system timer returns from the
> interrupt, there is a common code path which is checked on the way out
set_tsk_need_resched is the call?
> of any interrupt handler or system call.  This code path checks to see
> if the "need to schedule" flag is set, and if so, at that point
> instead of returning to the original process, the kernel will simply
> return to some other process.
> 
> I would suggest that you get a good introductory Linux book, such as
> "Linux Kernel Development" by Robert Love.  You might also check out
> the kernelnewbies.org website and mailing list, where you are more
> likely to get answers to basic introductory questions like this.
> 
> Regards,
> 
> 						- Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2012-10-05 13:27   ` Theodore Ts'o
  2012-10-05 14:03     ` Iain Fraser
  2012-10-05 18:05     ` anish kumar
@ 2012-10-05 18:15     ` Iain Fraser
  2 siblings, 0 replies; 27+ messages in thread
From: Iain Fraser @ 2012-10-05 18:15 UTC (permalink / raw)
  To: Theodore Ts'o, Iain Fraser, linux-kernel

Actually Theodore I've been thinking about your reply. Surely the
kernel doesn't care about a processes locks. Because a process can be
pre-empted at any-time. Isn't that the same as allowing
a process to be scheduled in interrupt context?

I understand the other reason, i.e. not allowing the idle process to
sleep is critical. And also appreciate that async scheduling a process
( other than preemption ) is very unfair to say the least :)

Cheers
Iain

On Fri, Oct 5, 2012 at 2:27 PM, Theodore Ts'o <tytso@mit.edu> wrote:
> On Fri, Oct 05, 2012 at 09:51:55AM +0100, Iain Fraser wrote:
>>
>> I understand the interrupts and softirq's run in interrupt context (
>> as opposed to process context ). But what I
>> don't understand is why you cannot sleep in interrupt context?
>
> Consider what happens with nested locks (and yes, we definitely need
> nested locks).  In order to prevent deadlocks, it is critical to have
> lock ordering; that is, you always take locks in a certain order.  If
> all processes take lock A, and then lock B, etc., then you won't have
> a problem where one process as lock A, and tries to get lock B, and
> another process has lock B, and tries to take lock A, and they wait
> for each other forever.
>
> If a process has a lock when it gets interrupted, the interrupt
> handler has no idea what locks may have already been taken.  So if a
> process has taken a mutex (or some other sleeping lock) B, and then
> the interrupt handler tries to take lock A, that's a perscription for
> deadlock.
>
> In addition, you must never sleep while holding a (non-sleeping)
> spinlock.  If the interrupt handler has interrupted a process which is
> holding a spinlock, then it simply may not sleep without triggering
> all sorts of other problems.
>
>> What I have read it states that it doesn't have a process to schedule
>> out. But interrupts use the interrupted processes
>> kernel stack just like a syscall. So surely it is possible to sleep
>> using that stack. Understandably It would be unfair on the process
>> that blocked through no fault of its own.
>>
>> Also if you are not allowed to sleep / schedule during interrupt
>> context. Then how does the system timer pre-empt processes by
>> calling schedule?
>
> The system timer sets the "need to reschedule" flag for that
> particular process.  Then as the system timer returns from the
> interrupt, there is a common code path which is checked on the way out
> of any interrupt handler or system call.  This code path checks to see
> if the "need to schedule" flag is set, and if so, at that point
> instead of returning to the original process, the kernel will simply
> return to some other process.
>
> I would suggest that you get a good introductory Linux book, such as
> "Linux Kernel Development" by Robert Love.  You might also check out
> the kernelnewbies.org website and mailing list, where you are more
> likely to get answers to basic introductory questions like this.
>
> Regards,
>
>                                                 - Ted

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Interrupt context
  2008-03-26 12:43       ` Octavian Purdila
@ 2008-03-26 21:53         ` Christopher Li
  0 siblings, 0 replies; 27+ messages in thread
From: Christopher Li @ 2008-03-26 21:53 UTC (permalink / raw)
  To: Octavian Purdila; +Cc: Codrin Alexandru Grajdeanu, linux-sparse

On Wed, Mar 26, 2008 at 5:43 AM, Octavian Purdila <tavi@cs.pub.ro> wrote:
>  You don't need to change the build system, you got all the information you
>  need in the final deliverable of the build (vmlinux or the kernel module).

How do you write to the ELF object? Can you write to ELF64 then you shouldn't
have the size limit. I am not a big fan of loading everything into one big ELF
file. I image it would be useful to only load the module as you needed.

>
>  OK, so you think that the serializer approach is still the way to go then?
>

Depend on what you actually serialized. In the ideal world, you can save and
load the compiled linearized byte code with symbol informations. That way
you don't lose any information during the serialization.

Chris

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Interrupt context
  2008-03-25  2:57     ` Christopher Li
@ 2008-03-26 12:43       ` Octavian Purdila
  2008-03-26 21:53         ` Christopher Li
  0 siblings, 1 reply; 27+ messages in thread
From: Octavian Purdila @ 2008-03-26 12:43 UTC (permalink / raw)
  To: Christopher Li; +Cc: Codrin Alexandru Grajdeanu, linux-sparse

On Tuesday 25 March 2008, Christopher Li wrote:
>
> BTW, besides linking what else do the ELF format buys you?
>

You don't need to change the build system, you got all the information you 
need in the final deliverable of the build (vmlinux or the kernel module).

>
> >  For this second try, we were thinking about replacing the serializer
> > with a thiner layer which would just save the call graph information
> > together with the associated interrupt context function / sleeping
> > function attributes in the object files.
>
> I would like to see some thing more general. For each file, it saves
> the information:
>
> 1) What symbol does it provide as extern.
> 2) What symbol does it accessed.
> 3) The linearized byte code for each function emits. (serialized of
> the entrypoint
>     for each function).
>
> And then, you would be able to perform a lot of checking on this.
>

OK, so you think that the serializer approach is still the way to go then? 

Thanks,
tavi







^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Interrupt context
  2008-03-25  1:34   ` Octavian Purdila
@ 2008-03-25  2:57     ` Christopher Li
  2008-03-26 12:43       ` Octavian Purdila
  0 siblings, 1 reply; 27+ messages in thread
From: Christopher Li @ 2008-03-25  2:57 UTC (permalink / raw)
  To: Octavian Purdila; +Cc: Codrin Alexandru Grajdeanu, linux-sparse

On Mon, Mar 24, 2008 at 6:34 PM, Octavian Purdila <tavi@cs.pub.ro> wrote:
> On Monday 24 March 2008, Christopher Li wrote:
>  Yes, you are right, we need to have the complete call graph of the whole
>  kernel and kernel modules we want to check. We developed a prototype
>  some time ago, but we never manage to move from the prototype to something
>  that could be used out in the real world.

Interesting. I did some hack on the serialize of the sparse output as well.

>  The idea which we explored for the prototype was to serialize the sparse state
>  and save it into the object files in a private section. The linker would than
>  take care of aggregating the sparse state into the kernel image or kernel
>  modules. The second stage loads the saved state, create the call graph,
>  propagate the interrupt/softirq context around and finally check if schedule
>  was called from interrupt context -- the check itself was really broad as we
>  did not do any data flow analysis.
>
>  The nice thing about this approach is that at least in theory would allow all
>  sorts of global analysis, not only this particular (sleeping in interrupt)
>  check. And we actually started with the idea of using sparse itself to
>  generate the serializer, but we ended up patching the generate code
>  manually - we abandoned the idea of adding sparse annotations to sparse code
>  to get things right as we realized that we are moving away from our goal.

I want to have sparse generate the the serializer code as well. One problem
I run into is that, a lot of the sparse C structure member are within the
union. The serialize code needs to understand the object type in order to access
the member specific to this type inside the union. It need some fairly
complicate
data flow analyze code to trace the sparse code itself how it access the union
member. I end up do it by hand as well :-)

>
>  But, what we obtain after the first stage was a vmlinux over 2GB in size,
>  which could not be processed by ELF utilities (we assumed that we hit some
>  limitations in the ELF32 format). So in the end its not so practical.

My plan is to write a symbol mapping  to perform the symbol look up.
For each extern symbol, you can look up to a object file name and an offset
within that object file to locate the symbol.

Then with the help from the serializer, you can load the that object file
into memory.

BTW, besides linking what else do the ELF format buys you?

Whatever file format, I want it to store the linearized byte code rather
than the machine code.

>  For this second try, we were thinking about replacing the serializer with a
>  thiner layer which would just save the call graph information together with
>  the associated interrupt context function / sleeping function attributes in
>  the object files.

I would like to see some thing more general. For each file, it saves
the information:

1) What symbol does it provide as extern.
2) What symbol does it accessed.
3) The linearized byte code for each function emits. (serialized of
the entrypoint
    for each function).

And then, you would be able to perform a lot of checking on this.

Chris

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Interrupt context
  2008-03-24 21:00 ` Christopher Li
@ 2008-03-25  1:34   ` Octavian Purdila
  2008-03-25  2:57     ` Christopher Li
  0 siblings, 1 reply; 27+ messages in thread
From: Octavian Purdila @ 2008-03-25  1:34 UTC (permalink / raw)
  To: Christopher Li; +Cc: Codrin Alexandru Grajdeanu, linux-sparse

On Monday 24 March 2008, Christopher Li wrote:
>
> I don't think two pass is enough. You need to build the call graph
> for pretty much every function. Because the irq handler function might
> call other function which calls other function which calls schedule().
>
> I don't think you can go very far without doing any control flow
> and data flow analyze. e.g. kmalloc() can go to sleep or not depend
> on the allocation flag (GFP_ATOMIC).
>
> Which points back to the proposal of:
> a) allow sparse to access  function from different files.
> b) building the call graph for every function in the kernel.
>


Hi Chris,

Yes, you are right, we need to have the complete call graph of the whole 
kernel and kernel modules we want to check. We developed a prototype 
some time ago, but we never manage to move from the prototype to something 
that could be used out in the real world.

The idea which we explored for the prototype was to serialize the sparse state 
and save it into the object files in a private section. The linker would than 
take care of aggregating the sparse state into the kernel image or kernel 
modules. The second stage loads the saved state, create the call graph, 
propagate the interrupt/softirq context around and finally check if schedule 
was called from interrupt context -- the check itself was really broad as we 
did not do any data flow analysis.

The nice thing about this approach is that at least in theory would allow all 
sorts of global analysis, not only this particular (sleeping in interrupt) 
check. And we actually started with the idea of using sparse itself to 
generate the serializer, but we ended up patching the generate code 
manually - we abandoned the idea of adding sparse annotations to sparse code 
to get things right as we realized that we are moving away from our goal.

But, what we obtain after the first stage was a vmlinux over 2GB in size, 
which could not be processed by ELF utilities (we assumed that we hit some 
limitations in the ELF32 format). So in the end its not so practical.

For this second try, we were thinking about replacing the serializer with a 
thiner layer which would just save the call graph information together with 
the associated interrupt context function / sleeping function attributes in 
the object files. 

Any comments / suggestions are greatly appreciated.

Thanks,
tavi







-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Interrupt context
  2008-03-23 21:44 Interrupt context Codrin Alexandru Grajdeanu
@ 2008-03-24 21:00 ` Christopher Li
  2008-03-25  1:34   ` Octavian Purdila
  0 siblings, 1 reply; 27+ messages in thread
From: Christopher Li @ 2008-03-24 21:00 UTC (permalink / raw)
  To: Codrin Alexandru Grajdeanu; +Cc: linux-sparse, Octavian Purdila

On Sun, Mar 23, 2008 at 2:44 PM, Codrin Alexandru Grajdeanu
<grcodal@gmail.com> wrote:
>   To test this, sparse would be required to run twice. First to get all
>   interrupt context functions, by verifying what arguments are passed to
>   irq_handler_t() and what values are passed to the function pointers in

You can identify the interrupt handler by return type is "irqreturn_t".

>   struct timer_list, softirq_action and tasklet_struct. The second run

That is harder.

>   would generate the call graph for this function and would verify if
>   schedule() is called inside their call graph.

I don't think two pass is enough. You need to build the call graph
for pretty much every function. Because the irq handler function might
call other function which calls other function which calls schedule().

I don't think you can go very far without doing any control flow
and data flow analyze. e.g. kmalloc() can go to sleep or not depend
on the allocation flag (GFP_ATOMIC).

Which points back to the proposal of:
a) allow sparse to access  function from different files.
b) building the call graph for every function in the kernel.

Chris

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Interrupt context
@ 2008-03-23 21:44 Codrin Alexandru Grajdeanu
  2008-03-24 21:00 ` Christopher Li
  0 siblings, 1 reply; 27+ messages in thread
From: Codrin Alexandru Grajdeanu @ 2008-03-23 21:44 UTC (permalink / raw)
  To: linux-sparse; +Cc: Octavian Purdila

Hi all,

 I am a student from Politehnica University of Bucharest studying
 Computer Science. I would like to add some new kernel source checks
 based on sparse. The first idea would be to test if from interrupt
 context sleepy functions are called.
 To test this, sparse would be required to run twice. First to get all
 interrupt context functions, by verifying what arguments are passed to
 irq_handler_t() and what values are passed to the function pointers in
 struct timer_list, softirq_action and tasklet_struct. The second run
 would generate the call graph for this function and would verify if
 schedule() is called inside their call graph.
 What do you think about this?

 Thank you,
 Codrin Grajdenau

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-15 21:40             ` Robert Love
  2003-04-15 23:02               ` Jeremy Hall
@ 2003-04-16  3:41               ` Jeremy Hall
  1 sibling, 0 replies; 27+ messages in thread
From: Jeremy Hall @ 2003-04-16  3:41 UTC (permalink / raw)
  To: Robert Love; +Cc: Jeremy Hall, linux-mm

With the tasklet version, I now have a different problem and don't fully 
understand how we got here.

Both CPUs are in snd_pcm_stop, which is a macro.  gdb has a hard time with 
this and can't reference some of the preprocessor code.

snd_pcm_stop is running for the same card but on different CPUs.  How'd 
that happen? I thought the tasklet wouldn't run ... oh but it only blocks 
itself from running on the local CPU twice

nice

Do I need to use spin_lock_irqsave or spin_lock to protect itself from 
running concurrently on different CPUs?

_J

In the new year, Robert Love wrote:
> On Mon, 2003-04-14 at 23:44, Jeremy Hall wrote:
> 
> > My quandery is where to put the lock so that both cards will use it.  I 
> > need a layer that is visible to both and don't fully understand the alsa 
> > architecture enough to know where to put it.
> 
> OK, I understand you now. :)
> 
> What is the relationship between the two things that are conflicting?
> 
> 	Robert Love
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-15 21:40             ` Robert Love
@ 2003-04-15 23:02               ` Jeremy Hall
  2003-04-16  3:41               ` Jeremy Hall
  1 sibling, 0 replies; 27+ messages in thread
From: Jeremy Hall @ 2003-04-15 23:02 UTC (permalink / raw)
  To: Robert Love; +Cc: Jeremy Hall, linux-mm, paul

[-- Attachment #1: Type: text/plain, Size: 2457 bytes --]

In the new year, Robert Love wrote:
> On Mon, 2003-04-14 at 23:44, Jeremy Hall wrote:
> 
> > My quandery is where to put the lock so that both cards will use it.  I 
> > need a layer that is visible to both and don't fully understand the alsa 
> > architecture enough to know where to put it.
> 
> OK, I understand you now. :)
> 
> What is the relationship between the two things that are conflicting?
> 
Two copies of snd_pcm_period_elapsed were running concurrently, one for 
one rme9652, one for the other.  Both are linked together as a single 
pcm_multi alsa device that an application is using.  Because both cards 
are on different interrupts, they can both run at the same time (the 
rme9652 interrupt handler calls snd_pcm_period_elapsed)

Somehow the second handler got called while the first was running, and the 
first had acquired a pcm spinlock.  Because the first had been suspended 
to run the second, deadlock occurred because the lock was never released.

There must be a common locking mechanism within the context of the 
interrupt handler so that two interrupt handlers running the same code 
don't deadlock.  The dependency occurs from within the pcm_multi layer, 
and that is where the "right" solution should be.

So to test, I wrote into the init routines, in the card discovery 
mechanism, a common lock, I called it dev_lock, and made it a requirement 
for running this function.

This was ok, except it meant that both devices can't run at the same time.

I wrote it up as a tasklet, which may or may not be the right solution 
either, but at least now it won't deadlock and maybe both will run at the 
same time.

I have attached both versions, and due to the way I applied it, you have 
to apply the irq diffs, then the tasklet diffs to get the current code.  
I'm not brave enough to say this should go in the alsa repository, but the 
tasklet version has not yet deadlocked and I have seen several XRUNs going 
by.  I cannot guarantee I have seen the special-case condition, but 
normally sooner or later deadlock occurs and it hasn't, running at LL 
settings for 00:10:09:32, which I consider a win.  Previously I'd see 
deadlock within the first couple minutes.

_J

> 	Robert Love
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>
> 


[-- Attachment #2: irq-diffs --]
[-- Type: text/plain, Size: 1477 bytes --]

--- rme9652.c	Tue Apr 15 09:40:41 2003
+++ rme9652.c.jhall	Tue Apr 15 09:37:15 2003
@@ -214,6 +214,7 @@
 	int dev;
 
 	spinlock_t lock;
+	spinlock_t *dev_lock;
 	int irq;
 	unsigned long port;
 	struct resource *res_port;
@@ -1950,13 +1951,13 @@
 void snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	rme9652_t *rme9652 = (rme9652_t *) dev_id;
+	unsigned long flags;
 
 	if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) {
 		return;
 	}
 
-	rme9652_write(rme9652, RME9652_irq_clear, 0);
-
+	spin_lock_irqsave(rme9652->dev_lock, flags);
 	if (rme9652->capture_substream) {
 		snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
 	}
@@ -1964,6 +1965,8 @@
 	if (rme9652->playback_substream) {
 		snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 	}
+	spin_unlock_irqrestore(rme9652->dev_lock, flags);
+	rme9652_write(rme9652, RME9652_irq_clear, 0);
 }
 
 static snd_pcm_uframes_t snd_rme9652_hw_pointer(snd_pcm_substream_t *substream)
@@ -2674,6 +2677,7 @@
 {
 	static int dev;
 	rme9652_t *rme9652;
+	static spinlock_t dev_lock;
 	snd_card_t *card;
 	int err;
 
@@ -2693,6 +2697,9 @@
 	rme9652 = (rme9652_t *) card->private_data;
 	card->private_free = snd_rme9652_card_free;
 	rme9652->dev = dev;
+	if (!dev)
+		spin_lock_init(&dev_lock);
+	rme9652->dev_lock = &dev_lock;
 	rme9652->pci = pci;
 
 	if ((err = snd_rme9652_create(card, rme9652, precise_ptr[dev])) < 0) {

[-- Attachment #3: tasklet-diffs --]
[-- Type: text/plain, Size: 2228 bytes --]

--- rme9652.c.jhall	Tue Apr 15 09:37:15 2003
+++ rme9652.c	Tue Apr 15 18:25:48 2003
@@ -214,7 +214,7 @@
 	int dev;
 
 	spinlock_t lock;
-	spinlock_t *dev_lock;
+	struct tasklet_struct interrupt_tasklet;
 	int irq;
 	unsigned long port;
 	struct resource *res_port;
@@ -326,6 +326,8 @@
 
 MODULE_DEVICE_TABLE(pci, snd_rme9652_ids);
 
+void rme9652_interrupt_tasklet(unsigned long arg);
+
 static inline void rme9652_write(rme9652_t *rme9652, int reg, int val)
 {
 	writel(val, rme9652->iobase + reg);
@@ -1951,13 +1953,20 @@
 void snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	rme9652_t *rme9652 = (rme9652_t *) dev_id;
-	unsigned long flags;
 
 	if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) {
 		return;
 	}
 
-	spin_lock_irqsave(rme9652->dev_lock, flags);
+	tasklet_hi_schedule(&rme9652->interrupt_tasklet);
+	rme9652_write(rme9652, RME9652_irq_clear, 0);
+}
+
+void
+rme9652_interrupt_tasklet(unsigned long arg)
+{
+	rme9652_t *rme9652 = (rme9652_t*)arg;
+
 	if (rme9652->capture_substream) {
 		snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
 	}
@@ -1965,8 +1974,6 @@
 	if (rme9652->playback_substream) {
 		snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 	}
-	spin_unlock_irqrestore(rme9652->dev_lock, flags);
-	rme9652_write(rme9652, RME9652_irq_clear, 0);
 }
 
 static snd_pcm_uframes_t snd_rme9652_hw_pointer(snd_pcm_substream_t *substream)
@@ -2560,6 +2567,7 @@
 		return err;
 
 	spin_lock_init(&rme9652->lock);
+	tasklet_init(&rme9652->interrupt_tasklet, rme9652_interrupt_tasklet, (unsigned long) rme9652);
 
 	rme9652->port = pci_resource_start(pci, 0);
 	if ((rme9652->res_port = request_mem_region(rme9652->port, RME9652_IO_EXTENT, "rme9652")) == NULL) {
@@ -2677,7 +2685,6 @@
 {
 	static int dev;
 	rme9652_t *rme9652;
-	static spinlock_t dev_lock;
 	snd_card_t *card;
 	int err;
 
@@ -2697,9 +2704,6 @@
 	rme9652 = (rme9652_t *) card->private_data;
 	card->private_free = snd_rme9652_card_free;
 	rme9652->dev = dev;
-	if (!dev)
-		spin_lock_init(&dev_lock);
-	rme9652->dev_lock = &dev_lock;
 	rme9652->pci = pci;
 
 	if ((err = snd_rme9652_create(card, rme9652, precise_ptr[dev])) < 0) {

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-15  3:44           ` Jeremy Hall
  2003-04-15  4:14             ` Jeremy Hall
@ 2003-04-15 21:40             ` Robert Love
  2003-04-15 23:02               ` Jeremy Hall
  2003-04-16  3:41               ` Jeremy Hall
  1 sibling, 2 replies; 27+ messages in thread
From: Robert Love @ 2003-04-15 21:40 UTC (permalink / raw)
  To: Jeremy Hall; +Cc: linux-mm

On Mon, 2003-04-14 at 23:44, Jeremy Hall wrote:

> My quandery is where to put the lock so that both cards will use it.  I 
> need a layer that is visible to both and don't fully understand the alsa 
> architecture enough to know where to put it.

OK, I understand you now. :)

What is the relationship between the two things that are conflicting?

	Robert Love

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-15  3:44           ` Jeremy Hall
@ 2003-04-15  4:14             ` Jeremy Hall
  2003-04-15 21:40             ` Robert Love
  1 sibling, 0 replies; 27+ messages in thread
From: Jeremy Hall @ 2003-04-15  4:14 UTC (permalink / raw)
  To: Jeremy Hall; +Cc: Robert Love, Jeremy Hall, linux-mm

In the new year, Jeremy Hall wrote:
> In the new year, Robert Love wrote:
> > On Mon, 2003-04-14 at 17:48, Jeremy Hall wrote:
> > 
> yes sorry for the silly dialog.  I'll post a backtrace so maybe it will be 
> more clear.
> 
and btw I appreciate your help. :)

Script started on Mon Apr 14 23:44:43 2003
Rainbow:/usr/src/linux-2.5.67 # gdb vmlinux
GNU gdb 5.3
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
gdb_interrupt (irq=4, dev_id=0x0, regs=0xdae4fc74)
    at arch/i386/lib/kgdb_serial.c:194
194	            continue ;
warning: shared library handler failed to enable breakpoint
(gdb) bt
#0  gdb_interrupt (irq=4, dev_id=0x0, regs=0xdae4fc74)
    at arch/i386/lib/kgdb_serial.c:194
#1  0xc010cd68 in handle_IRQ_event (irq=4, regs=0xdae4fc74, action=0xdffee640)
    at arch/i386/kernel/irq.c:214
#2  0xc010cfd1 in do_IRQ (regs=
      {ebx = -604748800, ecx = 32, edx = -604748632, esi = -604748632, edi = 10, ebp = -622527312, eax = -622534656, xds = 123, xes = 123, orig_eax = -252, eip = -1072561613, xcs = 96, eflags = 646, esp = -604748800, xss = -1049704384})
    at arch/i386/kernel/irq.c:395
#3  0xc010b60c in common_interrupt () at net/8021q/vlan.c:130
#4  0xc033b857 in snd_pcm_period_elapsed (substream=0xc16ec840)
    at sound/core/pcm_lib.c:2014
#5  0xc0340fa8 in snd_rme9652_interrupt (irq=10, dev_id=0xc1679dc8, 
    regs=0xdae4fd20) at sound/pci/rme9652/rme9652.c:1959
#6  0xc010cd68 in handle_IRQ_event (irq=10, regs=0xdae4fd20, action=0xc1700be0)
    at arch/i386/kernel/irq.c:214
#7  0xc010cfd1 in do_IRQ (regs=
      {ebx = -622534656, ecx = 1, edx = 578454, esi = -1049704384, edi = -604748800, ebp = -622527128, eax = -1049974272, xds = 123, xes = 123, orig_eax = -246, eip = -1070407894, xcs = 96, eflags = 514, esp = -622534656, xss = -1049704384}) at arch/i386/kernel/irq.c:395
#8  0xc010b60c in common_interrupt () at net/8021q/vlan.c:130
#9  0xc0332d81 in snd_pcm_stop (substream=0xc16ec9c0, state=4)
    at sound/core/pcm_native.c:712
#10 0xc0338030 in snd_pcm_update_hw_ptr_interrupt (substream=0xc16ec9c0)
    at sound/core/pcm_lib.c:179
#11 0xc033b88e in snd_pcm_period_elapsed (substream=0xc16ec9c0)
    at sound/core/pcm_lib.c:2016
#12 0xc0340fa8 in snd_rme9652_interrupt (irq=12, dev_id=0xc17171c8, 
    regs=0xdae4fe2c) at sound/pci/rme9652/rme9652.c:1959
#13 0xc010cd68 in handle_IRQ_event (irq=12, regs=0xdae4fe2c, action=0xc1700340)
    at arch/i386/kernel/irq.c:214
#14 0xc010cfd1 in do_IRQ (regs=
      {ebx = 1064997, ecx = 433565696, edx = -1069105792, esi = -1053505848, edi = -640172440, ebp = -622526864, eax = 3688, xds = 123, xes = 123, orig_eax = -244, eip = -1072398266, xcs = 96, eflags = 582, esp = -613946388, xss = -602417088}) at arch/i386/kernel/irq.c:395
#15 0xc010b60c in common_interrupt () at net/8021q/vlan.c:130
#16 0xc01481b8 in do_no_page (mm=0xdc17d840, vma=0xd6070cc0, 
    address=3204030464, write_access=1, page_table=0xd9d7be68, pmd=0xdb67ebec)
    at mm/memory.c:1332
#17 0xc014870c in handle_mm_fault (mm=0xdc17d840, vma=0xd6070cc0, 
    address=3204030464, write_access=1) at mm/memory.c:1483
#18 0xc0146e55 in get_user_pages (tsk=0xdbde8cc0, mm=0xdc17d840, 
    start=3204030464, len=102, write=1, force=0, pages=0x0, vmas=0x0)
    at mm/memory.c:718
#19 0xc01488b4 in make_pages_present (addr=3202351104, end=3204448256)
    at mm/memory.c:1580
#20 0xc0149f3c in do_mmap_pgoff (file=0x0, addr=3202351104, len=2097152, 
---Type <return> to continue, or q <return> to quit---
    prot=7, flags=34, pgoff=0) at mm/mmap.c:733
#21 0xc0111701 in old_mmap (arg=0x40c37e0c) at arch/i386/kernel/sys_i386.c:59
(gdb) up

> _J
> 
> > 	Robert Love
> > 
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 22:57         ` Robert Love
@ 2003-04-15  3:44           ` Jeremy Hall
  2003-04-15  4:14             ` Jeremy Hall
  2003-04-15 21:40             ` Robert Love
  0 siblings, 2 replies; 27+ messages in thread
From: Jeremy Hall @ 2003-04-15  3:44 UTC (permalink / raw)
  To: Robert Love; +Cc: Jeremy Hall, linux-mm

In the new year, Robert Love wrote:
> On Mon, 2003-04-14 at 17:48, Jeremy Hall wrote:
> 
> > > Note two processors can never run the _same_ handler for the same line. 
> > > A given line (say IRQ 8) is masked out on all processors while its
> > > handler.
> >
> > ok, but in this case, the same handler appears on two different lines, 
> > once for one RME card, once for the other.  It is theoretically possible 
> > that one line could be handled by once CPU and the other by the other CPU.
> 
> Yep.  You must obtain a spin lock and disable local interrupts if there
> is any shared data here (and I am sure there is).
> 
My quandery is where to put the lock so that both cards will use it.  I 
need a layer that is visible to both and don't fully understand the alsa 
architecture enough to know where to put it.
> > I'm still digging at this, so don't know yet how to answer this point.  
> > I'm thinking somehow we need to schedule the snd_pcm_period_elapsed, or 
> > force it to run in interrupt context.
> > 
> > I thought I had done the latter by moving the snd_rme9652_write to the 
> > bottom of the function so that it wouldn't clear the interrupt condition 
> > until after it processed the data.
> > 
> > but I guess I hadn't because it didn't make a difference.  This is why I 
> > raise the question about whether other interrupts can be called.
> 
> Well, as I have said, they can still run on OTHER processors, as long as
> its a different interrupt line (same handler is irrelevant).
> 
yes, I understand, but I had put nosmp and acpi=off in the boot line.  
There should have only been one processor, indeed I verified /proc/cpuinfo 
only showed one, although the kernel was compiled for SMP.

> So you can have these two handlers you speak of run at the same time.  I
> think you are trying to prevent that, no?
> 
I am trying to prevent one card from stopping while the other is reading.  
They can both read or write or whatever at the same time, but if state 
needs to be changed, everything needs to come to a stop so the state can 
change.

> Well, you cannot... but you can protect the shared data or hardware with
> a lock.  Grab a spin_lock in the handler prior to doing what you wish to
> protect.  This will prevent that chunk of code from running
> simultaneously.
> 
yes I understand what you are saying.

> Linus has a nice discussion on spin locks in Documentation/spinlocks.txt
> 
yes sorry for the silly dialog.  I'll post a backtrace so maybe it will be 
more clear.

_J

> 	Robert Love
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 21:48       ` Jeremy Hall
@ 2003-04-14 22:57         ` Robert Love
  2003-04-15  3:44           ` Jeremy Hall
  0 siblings, 1 reply; 27+ messages in thread
From: Robert Love @ 2003-04-14 22:57 UTC (permalink / raw)
  To: Jeremy Hall; +Cc: linux-mm

On Mon, 2003-04-14 at 17:48, Jeremy Hall wrote:

> > Note two processors can never run the _same_ handler for the same line. 
> > A given line (say IRQ 8) is masked out on all processors while its
> > handler.
>
> ok, but in this case, the same handler appears on two different lines, 
> once for one RME card, once for the other.  It is theoretically possible 
> that one line could be handled by once CPU and the other by the other CPU.

Yep.  You must obtain a spin lock and disable local interrupts if there
is any shared data here (and I am sure there is).

> > Further, if SA_INTERRUPT is specified then all other interrupts are
> > disabled, too, on the local processor.
> > 
> It would appear this may not be true, or my understanding of the code is 
> not sound (more likely) it would also appear rme9652_read might not be 
> able to differuntiate between being called for an RME card or another 
> card.

It is true :)

See irq.c for your architecture.  On x86, we have handle_IRQ_event():

	if (!(action->flags & SA_INTERRUPT))
		local_irq_enable();

It is called with interrupts disabled.  Unless SA_INTERRUPT is set,
though, they are enabled here.  Note this is the _local_ processor only.

> I'm still digging at this, so don't know yet how to answer this point.  
> I'm thinking somehow we need to schedule the snd_pcm_period_elapsed, or 
> force it to run in interrupt context.
> 
> I thought I had done the latter by moving the snd_rme9652_write to the 
> bottom of the function so that it wouldn't clear the interrupt condition 
> until after it processed the data.
> 
> but I guess I hadn't because it didn't make a difference.  This is why I 
> raise the question about whether other interrupts can be called.

Well, as I have said, they can still run on OTHER processors, as long as
its a different interrupt line (same handler is irrelevant).

So you can have these two handlers you speak of run at the same time.  I
think you are trying to prevent that, no?

Well, you cannot... but you can protect the shared data or hardware with
a lock.  Grab a spin_lock in the handler prior to doing what you wish to
protect.  This will prevent that chunk of code from running
simultaneously.

Linus has a nice discussion on spin locks in Documentation/spinlocks.txt

	Robert Love

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 21:18     ` Robert Love
@ 2003-04-14 21:48       ` Jeremy Hall
  2003-04-14 22:57         ` Robert Love
  0 siblings, 1 reply; 27+ messages in thread
From: Jeremy Hall @ 2003-04-14 21:48 UTC (permalink / raw)
  To: Robert Love; +Cc: Jeremy Hall, linux-mm

In the new year, Robert Love wrote:
> On Mon, 2003-04-14 at 17:09, Jeremy Hall wrote:
> 
> > with 2.5.67-mm2, it is SA_INTERRUPT|SA_SHIRQ and looks like it can call 
> > multiple interrupts at once.  I am not sure what SA_SHIRQ does, but this 
> > does not address the case where one CPU holds an interrupt for one card 
> > and the other CPU holds the interrupt for the other card.
> 
> SA_SHIRQ means "this interrupt line can be shared" -- thus each handler
> on the line needs to be able to differentiate when it is called whether
> or not its device actually caused the interrupt.
> 
oh, ok.

> Note two processors can never run the _same_ handler for the same line. 
> A given line (say IRQ 8) is masked out on all processors while its
> handler.
> 
ok, but in this case, the same handler appears on two different lines, 
once for one RME card, once for the other.  It is theoretically possible 
that one line could be handled by once CPU and the other by the other CPU.

> Further, if SA_INTERRUPT is specified then all other interrupts are
> disabled, too, on the local processor.
> 
It would appear this may not be true, or my understanding of the code is 
not sound (more likely) it would also appear rme9652_read might not be 
able to differuntiate between being called for an RME card or another 
card.

rme9652_read says

return readl(rme9652->iobase+reg);

oh yeah and it says if it can't read, it just returns.  I guess it can 
tell the difference.

> If you need to protect some data, grab a spin lock in your handler.
> 
I'm still digging at this, so don't know yet how to answer this point.  
I'm thinking somehow we need to schedule the snd_pcm_period_elapsed, or 
force it to run in interrupt context.

I thought I had done the latter by moving the snd_rme9652_write to the 
bottom of the function so that it wouldn't clear the interrupt condition 
until after it processed the data.

but I guess I hadn't because it didn't make a difference.  This is why I 
raise the question about whether other interrupts can be called.

_J

> > I moved the line 
> > 
> > rme9652_write(rme9652, RME9652_irq_clear, 0);
> > 
> > to after the snd_pcm_period_elapsed calls in the hopes that they would be 
> > run in interrupt context, but it did not make a difference.  The backtrace 
> > looks a little different, but it's still the same crash.
> 
> I am afraid I don't understand nearly enough of the context of the
> problem to know what to suggest next.
> 
> Keep hacking :)
> 
> 	Robert Love
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 21:09   ` Jeremy Hall
@ 2003-04-14 21:18     ` Robert Love
  2003-04-14 21:48       ` Jeremy Hall
  0 siblings, 1 reply; 27+ messages in thread
From: Robert Love @ 2003-04-14 21:18 UTC (permalink / raw)
  To: Jeremy Hall; +Cc: linux-mm

On Mon, 2003-04-14 at 17:09, Jeremy Hall wrote:

> with 2.5.67-mm2, it is SA_INTERRUPT|SA_SHIRQ and looks like it can call 
> multiple interrupts at once.  I am not sure what SA_SHIRQ does, but this 
> does not address the case where one CPU holds an interrupt for one card 
> and the other CPU holds the interrupt for the other card.

SA_SHIRQ means "this interrupt line can be shared" -- thus each handler
on the line needs to be able to differentiate when it is called whether
or not its device actually caused the interrupt.

Note two processors can never run the _same_ handler for the same line. 
A given line (say IRQ 8) is masked out on all processors while its
handler.

Further, if SA_INTERRUPT is specified then all other interrupts are
disabled, too, on the local processor.

If you need to protect some data, grab a spin lock in your handler.

> I moved the line 
> 
> rme9652_write(rme9652, RME9652_irq_clear, 0);
> 
> to after the snd_pcm_period_elapsed calls in the hopes that they would be 
> run in interrupt context, but it did not make a difference.  The backtrace 
> looks a little different, but it's still the same crash.

I am afraid I don't understand nearly enough of the context of the
problem to know what to suggest next.

Keep hacking :)

	Robert Love

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 18:56 ` Robert Love
  2003-04-14 19:32   ` Jeremy Hall
@ 2003-04-14 21:09   ` Jeremy Hall
  2003-04-14 21:18     ` Robert Love
  1 sibling, 1 reply; 27+ messages in thread
From: Jeremy Hall @ 2003-04-14 21:09 UTC (permalink / raw)
  To: Robert Love; +Cc: Jeremy Hall, linux-mm

In the new year, Robert Love wrote:
> On Mon, 2003-04-14 at 14:51, Jeremy Hall wrote:
> 
> Note if SA_INTERRUPT flag was given to request_irq() then the interrupt
> is a "fast" interrupt and runs with all interrupts disabled on the local
> processor.
> 
with 2.5.67-mm2, it is SA_INTERRUPT|SA_SHIRQ and looks like it can call 
multiple interrupts at once.  I am not sure what SA_SHIRQ does, but this 
does not address the case where one CPU holds an interrupt for one card 
and the other CPU holds the interrupt for the other card.

I moved the line 

rme9652_write(rme9652, RME9652_irq_clear, 0);

to after the snd_pcm_period_elapsed calls in the hopes that they would be 
run in interrupt context, but it did not make a difference.  The backtrace 
looks a little different, but it's still the same crash.

_J
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 19:32   ` Jeremy Hall
@ 2003-04-14 19:35     ` Robert Love
  0 siblings, 0 replies; 27+ messages in thread
From: Robert Love @ 2003-04-14 19:35 UTC (permalink / raw)
  To: Jeremy Hall; +Cc: linux-mm

On Mon, 2003-04-14 at 15:32, Jeremy Hall wrote:

> I am assuming you mean in some parent context.

No, I mean in the interrupt handler.  You can grab spin locks in
interrupt handlers.

You probably also want to disable interrupts locally.

	Robert Love

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 18:56 ` Robert Love
@ 2003-04-14 19:32   ` Jeremy Hall
  2003-04-14 19:35     ` Robert Love
  2003-04-14 21:09   ` Jeremy Hall
  1 sibling, 1 reply; 27+ messages in thread
From: Jeremy Hall @ 2003-04-14 19:32 UTC (permalink / raw)
  To: Robert Love; +Cc: Jeremy Hall, linux-mm

In the new year, Robert Love wrote:
> On Mon, 2003-04-14 at 14:51, Jeremy Hall wrote:
> 
> If you need to ensure concurrency is protected in your interrupt
> handler, grab a lock and disable interrupts around the critical region.
> 
I am assuming you mean in some parent context.

on alsa-devel, I wrote:

Consider the following:

Two RME9652's are running together and on different interrupts.

The master, in interrupt context, acquires its runtime->lock and begins
snd_pcm_update_hw_ptr_interrupt()

At the same time, the second card, the slave, is behind, still in play
mode, and wants to XRUN.  To do that, it must stop and restart all the
substreams connected to it.  To do that, it must acquire the runtime lock
of each, but the capture substream of the master is locked in another 
interrupt.

solution:

Is it acceptible if XRUN occurs in a pcm_multi environment to only restart
substreams related to that physical card? or is it necessary to restart
the whole device to maintain sample-sync?

I'm thinking you'd need to restart all devices.  Is this reasonable? as
in, am I reading the code correctly?

_J

The ideal solution would be to put both rme cards on the same interrupt, 
but I haven't been able to figure out how to do that, unless it is as 
simple as setting interrupt_line with setpci, but when the pcm_multi 
device is set up, it should find a way to figure out which interrupt(s) 
are functioning as a single device and mask them together somehow.

and this calling snd_pcm_period_elapsed from the interrupt handler but 
after clearing the interrupt (rme9652.c) i think is ultimately how this 
can occur.  I'm thinking that even IF they were both on the same interrupt 
this could occur because the irq is cleared before snd_pcm_period_elapsed 
runs.

_J

> 	Robert Love
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: interrupt context
  2003-04-14 18:51 interrupt context Jeremy Hall
@ 2003-04-14 18:56 ` Robert Love
  2003-04-14 19:32   ` Jeremy Hall
  2003-04-14 21:09   ` Jeremy Hall
  0 siblings, 2 replies; 27+ messages in thread
From: Robert Love @ 2003-04-14 18:56 UTC (permalink / raw)
  To: Jeremy Hall; +Cc: linux-mm

On Mon, 2003-04-14 at 14:51, Jeremy Hall wrote:

> On a UP machine, is it possible for two interrupts to occur at once? as 
> in, can card a create an interrupt while card b is in interrupt context?

Yes.  Normally, all interrupts are enabled (the interrupt system is on)
but the _current_ interrupt line is masked out.  Thus you will never get
a recursive interrupt (A while processing A) but you may get A while
processing B.

Note if SA_INTERRUPT flag was given to request_irq() then the interrupt
is a "fast" interrupt and runs with all interrupts disabled on the local
processor.

> what about an SMP machine operating in UP mode (nosmp)

By nature of above, yes.

If you need to ensure concurrency is protected in your interrupt
handler, grab a lock and disable interrupts around the critical region.

	Robert Love

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* interrupt context
@ 2003-04-14 18:51 Jeremy Hall
  2003-04-14 18:56 ` Robert Love
  0 siblings, 1 reply; 27+ messages in thread
From: Jeremy Hall @ 2003-04-14 18:51 UTC (permalink / raw)
  To: linux-mm

Hi,

On a UP machine, is it possible for two interrupts to occur at once? as 
in, can card a create an interrupt while card b is in interrupt context?

what about an SMP machine operating in UP mode (nosmp)

_J
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2012-10-05 18:15 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CA+bLfK5FPqFvU2xy7xKdV4LkAvmY6GAPFrB-4UBzn-cOunQ6Xg@mail.gmail.com>
2012-10-05  8:51 ` interrupt context Iain Fraser
2012-10-05  9:32   ` Borislav Petkov
2012-10-05 10:20     ` Iain Fraser
2012-10-05 10:34       ` Borislav Petkov
2012-10-05 13:27   ` Theodore Ts'o
2012-10-05 14:03     ` Iain Fraser
2012-10-05 18:05     ` anish kumar
2012-10-05 18:15     ` Iain Fraser
2008-03-23 21:44 Interrupt context Codrin Alexandru Grajdeanu
2008-03-24 21:00 ` Christopher Li
2008-03-25  1:34   ` Octavian Purdila
2008-03-25  2:57     ` Christopher Li
2008-03-26 12:43       ` Octavian Purdila
2008-03-26 21:53         ` Christopher Li
  -- strict thread matches above, loose matches on Subject: below --
2003-04-14 18:51 interrupt context Jeremy Hall
2003-04-14 18:56 ` Robert Love
2003-04-14 19:32   ` Jeremy Hall
2003-04-14 19:35     ` Robert Love
2003-04-14 21:09   ` Jeremy Hall
2003-04-14 21:18     ` Robert Love
2003-04-14 21:48       ` Jeremy Hall
2003-04-14 22:57         ` Robert Love
2003-04-15  3:44           ` Jeremy Hall
2003-04-15  4:14             ` Jeremy Hall
2003-04-15 21:40             ` Robert Love
2003-04-15 23:02               ` Jeremy Hall
2003-04-16  3:41               ` Jeremy Hall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.