• spin_lock、spin_lock_irq、spin_lock_irqsave区别


    void spin_lock(spinlock_t *lock);

    void spin_lock_irq(spinlock_t *lock);

    void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);


    1、spin_lock与spin_lock_irq区别

    在Linux内核中何时使用spin_lock,何时使用spin_lock_irqsave很容易混淆。首先看一下代码是如何实现的。

    spin_lock的调用关系

         spin_lock

                |

               + ----->  raw_spin_lock

    |

    +------>  _raw_spin_lock

                             |

                            +--------> __raw_spin_lock

     

        static inline void __raw_spin_lock(raw_spinlock_t *lock)  
        {  
                preempt_disable();  
                spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);  
                LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);  
        }  
    View Code

     

    spin_lock_irq的调用关系

        spin_lock_irq

                    |

                   +-------> raw_spin_lock_irq

                                               |

                                              +---------> _raw_spin_lock_irq

                                                                          |

                                                                          +------------> __raw_spin_lock_irq

        static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)  
        {  
                local_irq_disable();  
                preempt_disable();  
                spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);  
                LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);  
        } 
    View Code

    可以看出来他们两者只有一个差别:是否调用local_irq_disable()函数, 即是否禁止本地中断

    在任何情况下使用spin_lock_irq都是安全的。因为它既禁止本地中断,又禁止内核抢占

    spin_lock比spin_lock_irq速度快,但是它并不是任何情况下都是安全的。

    举个例子:进程A中调用了spin_lock(&lock)然后进入临界区,此时来了一个中断(interrupt),

    该中断也运行在和进程A相同的CPU上,并且在该中断处理程序中恰巧也会spin_lock(&lock)

    试图获取同一个锁。由于是在同一个CPU上被中断,进程A会被设置为TASK_INTERRUPT状态,

    中断处理程序无法获得锁,会不停的忙等,由于进程A被设置为中断状态,schedule()进程调度就

    无法再调度进程A运行,这样就导致了死锁

    但是如果该中断处理程序运行在不同的CPU上就不会触发死锁。 因为在不同的CPU上出现中断不会导致

    进程A的状态被设为TASK_INTERRUPT,只是换出。当中断处理程序忙等被换出后,进程A还是有机会

    获得CPU,执行并退出临界区。

    所以在使用spin_lock时要明确知道该锁不会在中断处理程序中使用。


    2、spin_lock_irq与spin_lock_irqsave区别

    spin_lock_irqsave在进入临界区前,保存当前中断寄存器flag状态,关中断,进入临界区,在退出临界区时,把保存的中断状态写回到中断寄存器

    spin_lock_irq在进入临界区前不保存中断状态,关中断,进入临界区,在退出临界区时,开中断。


    spin_lock_irqsave锁返回时,中断状态不会被改变,调用spin_lock_irqsave前是开中断返回就开中断。

    spin_lock_irq锁返回时,永远都是开中断,即使spin_lock_irq前是关中断


    总结:

    01)spin_lock_irq:既禁止本地中断,又禁止内核抢占;加锁后禁止中断,直到解锁后允许中断,故此该功能可保证时域的独立性;(中断中没有该标记锁的时候不会对中断有影响)

    02)spin_lock:快于spin_lock_irq,但不禁止中断,当在一个cpu下发生中断后,在时域上可打破该锁环境,当在对应中断服务函数中有同样锁的时候,因为得不到解锁,可能导致死锁;(对中断完整性用影响)

    03)spin_lock_irqsave:对中断状态有保护特性;(对中断完整性没有影响)

    转自:http://blog.csdn.net/zhanglei4214/article/details/6837697

    http://blog.csdn.net/lbo4031/article/details/8894830

  • 相关阅读:
    c# 第41节 异常处理
    c# 第40节 密封类、密封方法
    c# 第39节 抽象类、抽象方法
    c# 第38节 接口的实现
    c# 第37节 接口的实现与继承
    c# 第36节 接口的声明
    测试面试题集-接口测试
    Python接口自动化测试系列文章汇总
    Jmeter系列之简介与环境安装
    Python接口自动化之logging封装及实战
  • 原文地址:https://www.cnblogs.com/Ph-one/p/5328607.html
Copyright © 2020-2023  润新知