doubt about interrupts and spinlocks
Oscar Salvador
osalvador.vilardaga at gmail.com
Mon Oct 27 06:58:57 EDT 2014
Hi,
Sorry, I was a little bit confused on Friday, but I read about this topic
on the weekend and I think that now this is more clear for me.
My doubt is about spinlocks are working together with interrupts.
As far I could understand:
If you are working with a code that can handle and interrupt, and this
interrupt can hold a lock, you must use spinlocks with irq version(
spin_lock_irqsave and spin_lock_irqrestore) in the functions that you need
to lock, otherwise, if you acquire a lock in CPU0, and then an interrupt is
raised in the same CPU0 and tries to acquire the same lock, we will have a
deadlock problem.
But if you acquire a lock disabling the IRQ in the CPU0, and then an
interrupt is raised at CPU1 and tries to acquire a lock, the interrupt will
spin till the lock is released in the other function(the function that
acquire the lock first).
A graphical example would be:
static int hardware_tx(struct net_device *dev) /* This is the function that
the network subsystem calls when has a packet to transmit */
{
struct rtl_t *rtl_p = netdev_priv(dev);
int pkt_len = rtl8139_p->skb_d->len;
unsigned long flags;
spin_lock_irqsave(&rtl_p->lock, flags); /* We acquire a lock,
disabling the interrupts in the local CPU */
/*
Do some private stuff
Do some private stuff
At some point an interrupt is raised, so we go to the
handler
Since i_handler has to spin, we continue here
Do some private stuff
*/
spin_unlock_irqsave(&rtl_p->lock, flags); /* We are releasing the
lock, and put the interrupts in the old state( in this case enabled) */
/* This is safe since
kernel ensures that only one interrupt in the same line can be processed
at the same time, so since i_handler is executing, kernel it will not
execute it again, no? */
return 0;
}
static irqreturn_t i_handler(int irq, void *dev_id) /* This is the
interrupt handler */
{
struct rtl_t *rtl_p = netdev_priv(dev);
/* Now we are on the handler */
spin_lock(&rtl8139_p->lock); /* We try to acquire a lock, but we
can not since hardware_tx has already taken a lock, so we have to spin here
till hardware_tx finish his work*/
/*
Ok, hardware_tx released the lock, now we can continue
Do some private stuff
Do some private stuff
Do some private stuff
*/
spin_unlock(&rtl_p->lock, flags); /* Lock released */
}
Hopefully now I explained it better.
Thank you very much
Kind regards
2014-10-24 21:16 GMT+02:00 anish singh <anish198519851985 at gmail.com>:
> inline answers.
>
> On Fri, Oct 24, 2014 at 8:04 AM, Oscar Salvador <
> osalvador.vilardaga at gmail.com> wrote:
>
>> Hi!
>>
>> I have a doubt about interrupts and spin locks.
>> I'm not sure if I'm in the good way:
>>
>> When an interrupt is raised, the kernel (through do_IRQ and etc)
>> acknowledges the interrupt and locks this IRQ taking a spin lock, so any
>> other cpu can not handle this interrupt, and then the kernel executes the
>> handler, if there is a handler available for that interrupt.
>>
>> When we are on the handler interrupt , maybe we need to lock the cpu till
>> we finish( if we are in a network driver, may we need to process some TX/RX
>> packets ),
>> so if we have to lock the code we can do a spin_lock().
>> But with a spin_lock, even other CPU's can execute part of your code(code
>> that is not part of the handler interrupt).
>> For example:
>>
>> (this is an example in a network device driver)
>> The system has to transmit a packet, so network subsystem calls
>> ndo_start_xmit. Inside this function we take a lock disabling the
>> interrupts(spin_lock_irqsave) because we have to do some private things,
>> but suddenly an interrupt is raised and we go to the interrupt handler, we
>> take a spin_lock, we do some work (processing some RX/TX packets), and
>> exites from the interrupt handler, and then we come back to the
>> ndo_start_xmit when we were.
>>
>> As far I could understand( I have read
>> http://www.makelinux.net/ldd3/chp-5-sect-5 ), spin_lock_irqsave only
>> disables the interrupts for the local cpu(where the code is executed),
>> so I think that another cpu took the handler interrupt.
>>
> Yes this can happen and if you expect that the interrupt can come in other
> CPU then you should handle that as well.
> Generally interrupts are disabled so you won't get any interrupt on other
> CPU if any cpu is currently handling the interrupt.
> However your explained sceneraio happens for network packets and that is
> why kernel uses softirq mechanism for network
> packets. Read about softirq.
>
>> The problem is if I'm working with irq disabled, because I have to handle
>> a private structure and suddenly interrupts is taking place, the interrupt
>> can manipulate the code that I'm trying to keep safe.
>> Is there any advice? Maybe that is happened because the code within my
>> critical section on ndo_start_xmit has to be atomic? Otherwise it can go to
>> sleep and I can lose my lock?
>>
> Your question is not quite coherent.
>
>>
>> Thank you very much
>> Oscar Salvador
>>
>> _______________________________________________
>> Kernelnewbies mailing list
>> Kernelnewbies at kernelnewbies.org
>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20141027/9ff859a7/attachment.html
More information about the Kernelnewbies
mailing list