dragonex
驱动牛犊
驱动牛犊
  • 注册日期2002-04-15
  • 最后登录2008-09-12
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望14点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2317回复:6

SMP系统下KeAcquireSpinLock 的疑问。

楼主#
更多 发布于:2008-09-11 00:38
本论坛的一篇经验文章《Windows NT 驱动程序开发人员提示 -- 应注意避免的事项》中提到:

14. 一定不要在 ISR 或 SynchCritSection 例程中调用 KeAcquireSpinLock 和 KeReleaseSpinLock 或者其它任何使用可执行旋转锁的例程。  


但是,如果ISR中确实需要调用KeAcquireSpinLock怎么办?KeAcquireSpinLock 应该本来就是为解决多CPU情况下的问题。

请各位指教!
dragonex
驱动牛犊
驱动牛犊
  • 注册日期2002-04-15
  • 最后登录2008-09-12
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望14点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-09-11 00:42
KeAcquireSpinLock 会提升IRQL?

dragonex
驱动牛犊
驱动牛犊
  • 注册日期2002-04-15
  • 最后登录2008-09-12
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望14点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-09-11 11:13
call KeAcquireSpinLock when IRQL<=DISPATCH....
flyingkisser
驱动牛犊
驱动牛犊
  • 注册日期2005-04-09
  • 最后登录2011-01-05
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望48点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-09-12 09:49
因为KeAcquireSpinLock 会把irql提升到dpc,
你可以自己实现一个同步操作,类似spinlock,主要使用lock    bts和pause指令,如果你的isr比较简单,并且阻塞的时间比较短。
dragonex
驱动牛犊
驱动牛犊
  • 注册日期2002-04-15
  • 最后登录2008-09-12
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望14点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-09-12 11:14
多谢

windows下有lock    bts和pause这些指令么?你的意思是说自己做个提升到DIRQL的spinlock吧?
tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
5楼#
发布于:2008-09-17 21:20
为什么需要在ISR里面调用这个函数?
没必要在ISR里面调用这个函数啊

一个驱动程序运行的IRQL大概有3种

1.普通的level..比如passive.这是大多少代码运行的level
2.dispatch level.这个基本上都是同步要求的level
3.isr的level..

从1到3.一个比一个高

在单cpu的情况下
如果一个isr正在运行..那么系统会保证任何低于isr的level的代码都不会被运行
也就说你的isr在运行的时候是不用担心被别的低level的代码抢占的

而同时的...isr一样有一个spinlock.他跟普通用的executive spinlock不一样
他的irql不是dispatch level而是你的isr的hardware level
在多cpu的情况下
如果你的isr要访问的数据也会被别的代码访问
那么你需要别的代码去同步isr.而不是isr去跟别的代码同步...

明白了吗?
可以这样认为
isr是无视同步的..而别的代码去跟isr同步
别的代码需要获取isr的那个spinlock来做到同步
使用这个函数KeSynchronizeExecution

查一查msdn看看这个函数

通常的..spinlock的用法都是这样
KeAcquireSpinlock(..);
[...access some data...]
KeReleaseSpinlock(...);

而ISR的情况是这样的

内核调用..KeAcquireSpinlock(&InterruptObject->Spinlock,...);
内核接着调用你的ISR
内核调用..KeReleaseSpinlock(&InterruptObject->Spinlock,...);

也就是说你的ISR在运行的时候你已经获取了你的interrupt object里面的spinlock
对比一下上面的通常情况的部分

你就知道如果别的代码要ISR同步
他只是需要获取和释放interrupt object里面的spin lock就行来
这也就是KeSynchronizeExecution的功能

他的代码大概是这样的
BOOLEAN  KeSynchronizeExecution(IN PKINTERRUPT  Interrupt,IN PKSYNCHRONIZE_ROUTINE  SynchronizeRoutine,IN PVOID  SynchronizeContext)
{
     KeAcquireSpinlock(&Interrupt->Spinlock,...);
     SynchronizeRoutine(SynchronizeContext);
     KeReleaseSpinlock(&Interrupt->Spinlock,...);
}

也就是说你的isr和上面的SynchronizeRoutine都不需要去管spinlock
内核已经帮你同步好了
yunyanrong
驱动小牛
驱动小牛
  • 注册日期2003-04-18
  • 最后登录2013-03-02
  • 粉丝0
  • 关注0
  • 积分1040分
  • 威望457点
  • 贡献值1点
  • 好评度90点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2009-01-08 17:18
时至今日,方才明白tiamo老大这番话的真实含义,太感谢了!!!

祝2009年身体健康。
游客

返回顶部