0.driverbase-自旋锁(SpinLock)wrk代码分析
2014-05-04 19:18
260 查看
http://hgy413.com/1335.html
简介自旋锁的注意点和自旋锁实现原型代码
自旋锁是一种轻量级的多处理器间的同步机制(对单处理器无效) :roll:
它要求所占用的时间尽可能短(一般不超过25ms),因为此时别的处理器正在高速运转并等待锁的释放,所以不能长时间占有
与其他相比,采用自旋锁的好处是:不会被中断或调度打断(它运行在DISPATCH_LEVEL上,不会被软中断)
自旋锁注意点:
1.被自旋锁保护的临界区代码执行时不能睡眠。单核处理器下,获取到锁的线程睡眠,若恰好此时CPU调度的另一个执行线程也需要获取这个锁,则会造成死锁;多核处理器下,若想获取锁的线程在同一个处理器下,同样会造成死锁,若位于另外的处理器,则会长时间占用CPU等待睡眠的线程释放锁,从而浪费CPU资源
2. 一定不要使自旋锁 (Spin Lock) 保持锁定状态的时间超过您的需要。 要使系统获得更好的总体性能,请不要使任何系统范围内有效的自旋锁的锁定时间超过 25 微秒
3.一定不要通过调用 KeReleaseSpinLockFromDpcLevel 来释放 KeAcquireSpinLock 所获取的自旋锁,因为这会使原始 IRQL 无法被还原
4.自旋锁锁定时,一定不要调用 IoStartNextPacket。 这将使系统死锁
5.自旋锁锁定时,一定不要调用 IoCompleteRequest。 这将使系统死锁
6.一定不要在取消例程中调用 IoAcquireCancelSpinLock,因为该例程被调用时已经获取了系统级的取消自旋锁
7.在自旋锁锁定时,一定不要调用驱动程序以外的代码,因为这会引起死锁
简单贴下WRK下自旋锁的实现代码:
1.初始化
2.获取
3. 释放
简介自旋锁的注意点和自旋锁实现原型代码
自旋锁是一种轻量级的多处理器间的同步机制(对单处理器无效) :roll:
它要求所占用的时间尽可能短(一般不超过25ms),因为此时别的处理器正在高速运转并等待锁的释放,所以不能长时间占有
与其他相比,采用自旋锁的好处是:不会被中断或调度打断(它运行在DISPATCH_LEVEL上,不会被软中断)
自旋锁注意点:
1.被自旋锁保护的临界区代码执行时不能睡眠。单核处理器下,获取到锁的线程睡眠,若恰好此时CPU调度的另一个执行线程也需要获取这个锁,则会造成死锁;多核处理器下,若想获取锁的线程在同一个处理器下,同样会造成死锁,若位于另外的处理器,则会长时间占用CPU等待睡眠的线程释放锁,从而浪费CPU资源
2. 一定不要使自旋锁 (Spin Lock) 保持锁定状态的时间超过您的需要。 要使系统获得更好的总体性能,请不要使任何系统范围内有效的自旋锁的锁定时间超过 25 微秒
3.一定不要通过调用 KeReleaseSpinLockFromDpcLevel 来释放 KeAcquireSpinLock 所获取的自旋锁,因为这会使原始 IRQL 无法被还原
4.自旋锁锁定时,一定不要调用 IoStartNextPacket。 这将使系统死锁
5.自旋锁锁定时,一定不要调用 IoCompleteRequest。 这将使系统死锁
6.一定不要在取消例程中调用 IoAcquireCancelSpinLock,因为该例程被调用时已经获取了系统级的取消自旋锁
7.在自旋锁锁定时,一定不要调用驱动程序以外的代码,因为这会引起死锁
简单贴下WRK下自旋锁的实现代码:
1.初始化
FORCEINLINE VOID NTAPI KeInitializeSpinLock ( __out PKSPIN_LOCK SpinLock ) { *SpinLock = 0; }KSPIN_LOCK SpinLock实际是一个操作系统相关的无符号整数,初始化,置为0,有信号状态
2.获取
//宏定义 #define KeAcquireSpinLock(SpinLock, OldIrql) \ *(OldIrql) = KeAcquireSpinLockRaiseToDpc(SpinLock) --> KIRQL KeAcquireSpinLockRaiseToDpc (__inout PKSPIN_LOCK SpinLock) { KIRQL OldIrql; //提IRQL到DISPATCH_LEVEL,这样不会发生线程切换(线程调度也是在DISPATCH_LEVEL) //单核下,由于线程不会被切换,自然就达到了互斥效果 OldIrql = KfRaiseIrql(DISPATCH_LEVEL); KxAcquireSpinLock(SpinLock); return OldIrql; //返回原始的IRQL } --> VOID KxAcquireSpinLock (__inout PKSPIN_LOCK SpinLock) { if (InterlockedBitTestAndSet64((LONG64 *)SpinLock, 0)) { KxWaitForSpinLockAndAcquire(SpinLock); } return; } -->InterlockedBitTestAndSet BOOLEAN InterlockedBitTestAndSet (IN LONG *Base,IN LONG Bit) { __asm { mov eax, Bit mov ecx, Base //lock指令是一种前缀,它可与其他指令联合,用来维持总线的锁存信号直到与其联合的指令执行完为止。当CPU与其他CPU协同工作时,该指令可避免破坏有用信息。 lock bts [ecx], eax//eax传入的是0,所以bts是把*SpinLock的第0位设置为1 setc al }; } --> ULONG64 KxWaitForSpinLockAndAcquire (__inout PKSPIN_LOCK SpinLock) { ULONG64 SpinCount = 0; // Wait for spin lock to become free.循环等待,直到SpinLock为0 do { do { KeYieldProcessor(); } while (*(volatile LONG64 *)SpinLock != 0); } while(InterlockedBitTestAndSet64((LONG64 *)SpinLock, 0)); return SpinCount; }
3. 释放
VOID KeReleaseSpinLock (__inout PKSPIN_LOCK SpinLock, __in KIRQL OldIrql) { KxReleaseSpinLock(SpinLock); KeLowerIrql(OldIrql);// 恢复IRQL return; } --> VOID KxReleaseSpinLock (__inout PKSPIN_LOCK SpinLock) { InterlockedAnd64((LONG64 *)SpinLock, 0);//释放时进行与操作设置其为0 return; }
相关文章推荐
- Webrtc delay-base-bwe代码分析(1): RateStatistics模块
- 结合代码分析--BaseServlet存在的意义(刚接触servlet的必看)
- 0.driverbase-枚举进程,枚举模块,操作注册表随手代码
- Webrtc delay-base-bwe代码分析(2): InterArrival模块
- chrome代码中base::JSONReader类的阅读分析(一)
- Webrtc delay-base-bwe代码分析(3): OveruseEstimator模块
- Webrtc delay-base-bwe代码分析(4): OveruseDetector模块
- OSChina App代码分析之BaseApplication
- python中BaseHTTPServer.py代码阅读分析
- 《linux 内核完全剖析》 由逻辑地址转换成线性地址代码分析 get_base get_limit 代码分析笔记
- Webrtc delay-base-bwe代码分析(5): AimdRateControl模块
- Webrtc delay-base-bwe代码分析(6): 整体分析
- wojilu系统的ORM代码解析-[源代码结构分析,ObjectBase基类分析]
- spinlock与linux内核调度的关系,那么为什么信号量保护的代码可以睡眠而自旋锁就不能呢?
- wdk中使用自旋锁SpinLock的规则及原因分析
- Linux下原子操作(信号量 自旋锁)的实现原理和底层代码分析
- C++卷积神经网络实例:tiny_cnn代码详解(10)——layer_base和layer类结构分析
- cocos2d-x 3.0 示例代码分析3:BaseTest
- PreEmptive代码分析技术交流会免费报名中……
- NS2 分裂机制及代码分析<一>