static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp;
__asm__ __volatile__(
"1: ldrex %0, [%1]\n"
" teq %0, #0\n"
WFE("ne")
" strexeq %0, %2, [%1]\n"
" teqeq %0, #0\n"
" bne 1b"
: "=&r" (tmp)
: "r" (&lock->lock), "r" (1)
: "cc");
smp_mb();
}
这段内嵌汇编首先检查lock->lock,如果等于0,就表明现在是unlock状态,就把lock->lock置位1,表示lock状态。这段汇编里边,关键的三个指令是:ldrex, strexeq, WFE, 前两个指令实现独占访问储存器,保证"读取-修改-写入”在芯片级是原子的,而WFE是wait for event, 和WFI类似,只是他可以被SEV指令唤醒,在spin_unlock()的时候,会发出SEV。
具体可以参见蜗蜗的文章:
了解SMP 平台下的spin_lock之后,还是那两个问题,进程上下文重入和中断上下文重入。第一个问题已经澄清,那第二个问题呢?重现之前的情景:进程A陷入内核,获取spin_lock,正在执行临界区代码,被本地IRQ打断,且ISR中要获取同一个spin_lock, 在SMP下,ISR就要调用WFE进入low-power-mode,这样持有锁的内核路径也得不到运行,所以无法释放锁资源,ISR也就只能一直WFE,本地CPU就这样挂掉了。当然,当IRQ在其他CPU上的时候,这种情况是不会发生的,另一个CPU为WFE直到本地CPU释放锁资源。
所以,这样又回到之前的解决办法,如果ISR有可能重入临界区,那么就应该使用 spin_lock_irq() 而非 spin_lock()。如果不这样使用,在UP下,临界数据将错乱,而在SMP下,CPU将死锁。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-77053-11.html
原料环节不能有蛆吗
不对等