当前位置:  开发笔记 > 运维 > 正文

在拿着自旋锁时自动不安全返回?

如何解决《在拿着自旋锁时自动不安全返回?》经验,为你挑选了1个好方法。

受人尊敬的书籍Linux Driver Development

flags传递给的参数spin_unlock_irqrestore必须是传递给的相同变量spin_lock_irqsave.你还必须打电话spin_lock_irqsavespin_unlock_irqrestore使用相同的功能; 否则你的代码可能会破坏某些架构.

然而,我找不到与内核代码本身捆绑在一起的官方文档所要求的任何此类限制.我发现违反此指南的驱动程序代码.

显然,调用spin_lock_irqsavespin_unlock_irqrestore从单独的函数调用并不是一个好主意,因为你应该在保持锁定的同时最小化完成的工作(禁用中断,不能少!).但是如果对内核进行了更改,那么如果小心翼翼地完成它,它是否真的不会违反API合同,或者它是否仍然禁止这样做?

如果在某些时候删除了限制,它是否适用于版本3.10.17?



1> Kaz..:

这只是一个猜测,但可能不清楚地指的是如果您尝试使用非局部变量或存储位置标记时可能发生的潜在错误.

基本上,flags必须是当前执行上下文的私有,这就是为什么spin_lock_irqsave一个宏取名的宏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扩展为机器代码,将当前标志保存在某个寄存器中,然后获取锁,然后将该寄存器保存到指定flags目标.在这种情况下,有缺陷的代码实际上是安全的.如果扩展代码将标志保存到flags调用者指定的实际对象中,然后尝试获取锁定,那么它就会被破坏.

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有