这只是一个猜测,但可能不清楚地指的是如果您尝试使用可能发生的潜在错误nonlocal变量或存储位置flags.
基本上,flags必须是当前执行上下文私有的,这就是为什么spin_lock_irqsave
是一个宏,其名称为flags
. While flags正在保存,您还没有自旋锁。
这与不同函数中的锁定和解锁有何关系:
考虑一些驱动程序开发人员可能编写的两个函数:
void my_lock(my_object *ctx)
{
spin_lock_irqsave(&ctx->mylock, ctx->myflags); /* BUG */
}
void my_unlock(my_object *ctx)
{
spin_unlock_irqrestore(&ctx->mylock, ctx->myflags);
}
这是一个错误,因为当时ctx->myflags
已写入,锁尚未持有,并且它是对其他上下文和处理器可见的共享变量。本地标志必须保存到堆栈上的私有位置。然后,当调用者拥有锁时,可以将标志的副本保存到独占拥有的对象中。换句话说,它可以这样修复:
void my_lock(my_object *ctx)
{
unsigned long flags;
spin_lock_irqsave(&ctx->mylock, flag);
ctx->myflags = flags;
}
void my_unlock(my_object *ctx)
{
unsigned long flags = ctx->myflags; /* probably unnecessary */
spin_unlock_irqrestore(&ctx->mylock, flags);
}
如果不能像这样修复它,那么实现需要包装 IRQ 自旋锁的更高级别原语将非常困难。
它如何依赖于拱门:
假设spin_lock_irqsave
扩展为机器代码,将当前标志保存在某个寄存器中,then获取锁,并且then将该寄存器保存到指定的flags
目的地。在这种情况下,有错误的代码实际上是安全的。如果扩展代码将标志保存到实际的flags
调用者指定的对象,然后尝试获取锁,然后它就被破坏了。