spinlock

 spinlock本身是原子操作的。会禁用抢占和避免multi-core竞争.它不能长期持有。

1. spinlock哪些场合需要?

不能进入睡眠的情况下: 中断处理中,tasklet中。还有有些很短的临界区,如果用信号量,会有进程睡眠和再次唤醒,代价很高,可以用spin_lock.

使用时要先初始化: SPIN_LOCK_UNLOCKED

2. 为什么用户空间不需要spinlock

用户不需要了解多个cpu的互斥。

3. 为什么spinlock要禁止抢占

应该是spinlock代表当前cpu获得进入临界区的权利。如果获得后发生抢占,另一个进程也访问该临界区,会发生死锁。对于单cpu系统,如果不开启抢占,那么spinlcok可以认为是空操作。

4. 会不会有获取spinlock后,该进程时间片到期的情况,这时内核如何处理?

linux调度器不需要传统意义上时间片的概念。因此如果抢占被禁止, 除非临界区内有主要放弃cpu(但是睡眠等不被允许),是不会重新调度的。

CFS处理周期性调度器的时候,也是在tick中设置TIF_NEED_RESCHED flag,要打开抢占的情况下,才会在tick中断返回时候调用scudle().

5. spinlock中保护的代码不能睡眠,要注意哪些?

要注意防止临界区被中断打断,而打断的代码中需要获取同样的spin_lock获取死锁。这样需要禁用local irq或者bh:

适用于自旋锁的核心规则是:任何拥有自旋锁的代码都必须是原子的。它不能被休眠,事实上,它不能因为任何原因放弃处理器,除了服务中断以外(这个中断服务没有访问已经获取自旋锁的数据)。内核抢占的情况由自旋锁代码本身处理,任何时候,只要内核代码拥有自旋锁,在相关处理器上的抢占就会被禁止。

函数spin_lock_bh用于获取指定锁,同时它会禁止所有下半部的执行。由于下半部会抢占进程上下文中的代码,所以当下半部与进程上下文共享数据时,必须对进程上下文中的共享数据进行保护,所以需要加锁的同时还有禁止下半部的执行。

同类的tasklet(同一个)不可能同时运行,所以对于同类的tasklet的共享数据不需要保护。但是当数据被两个不同种类的tasklet共享时,就需要在访问下半部中的数据前先获得一个普通的自旋锁。这里不需要禁止下半部,因为在同一个处理器上决不会有tasklet相互抢占的情况。

对于软中断,无论是否同种类型,如果数据被软中断共享,那么它必须得到锁的保护。因为即使是同种类型的两个软中断也可以同时运行在一个系统的多个处理器上。但是,同一个处理器上的一个软中断决不会抢占另一个软中断,因此,不需要禁止下半部。


spin_lock_irq vs spin_lock_irqsave
1. spin_lock_irq spin_unlock_irq 之后恢复本地中断
2. spin_lock_irqsave spin_unlock_irqrestore 恢复之前保存的本地中断flag.
这样说明spin_lock_irq使用前要确保本地irq 是打开的(因为unlock不管之前状态而打开本地中断)

spin_lock_irq 使用场景:当中断中和函数中都需要访问同样的数据的时候,需要在函数中使用spin_lock_irq,因为这样可以防止
函数中已经获取spinlock后,被当前cpu中断打断,而中断中又要等待spinlock导致死锁。但是在其他的cpu中断中不会有问题。






你可能感兴趣的:(Linux,每日心得)