阅读:2286回复:5
同步的一点心得
最近因为写的东西涉及到了smp相关的东西,随之而来的同步问题困扰了我很长时间。
这几天被郁闷了这么久,写点东西出来给大家共享一下,呵呵,别说我土 先说一下在单cpu下的同步。如果你的驱动仅仅运行在单cpu下,一个irql就可以搞定 所有的同步问题,由低到高:PASSIVE,APC,DISPATCH,只有高于当前的irql才能中断 当前线程。但是如果在smp机器下,其它的cpu就不会受irql的限制,同步问题得自己 搞定了,没有同步量就不会有稳定的驱动。 同步量,开始的时候看ddk,随便选了几个东西就来用。而且DDK里面也提供了很多, 内核的event,mutex,fastmutex,semaphore。如果你在DISPATCH LEVEL下面使用这些 同步量的话,会有随机死机的情况发生,因为DISPATCH LEVEL下面不允许等待-- 而这些操作只有在无法立刻满足获取条件的时候才会进入等待状态,也就是随机死 的原因。而且查错也比较麻烦 只有spinlock才可以在DISPATCH LEVEL下面正常使用。因为spinlock的实现机制 很简单,就是测试并置位一个整数值(BTS),满足则返回,不满足则在一个小循环 里等待,所以不会触犯上面的那个条件。 不过正是因为spinlock太简单了,所以如果同一个cpu两次试图获取一个spinlock而 又没有释放的话,那这个cpu就真的锁住了。 不过这种情况大家可能很少碰到,前面的帖子也有人问过这个问题:我重复多次获 取一个spinlock,怎么还是跑得好好的?我可以确定的是,这一定是一台单cpu机器。 因为win系统(2k,xp)下,我跟踪得到的结果是,spinlock的acquire/release都是 空操作--也就是说spinlock在单cpu下面是摆设。只有在smp机器里,spinlock才 真的会发挥作用:acquire是在一个小循环内反复测试一个整数值,release直接把 这个整数值设为0。这种平台下cpu才会出现真的锁住的情况,设计挺好的,不过不 太利于查错,ms考虑的就是多,呵呵 再说一下我遇到的这个问题,2k,smp平台。在MiniportSend/ProtocolReceivePacket 里面设置的同步,等待一个spinlock来访问共享资源。因为ddk里面说这两个回调是 运行在DISPATCH LEVEL下,按理说不会被自己的cpu打断。可是我在实际用的时候 会有偶尔的死锁现象。郁闷了3,4天,偶尔的一次突然发现进入MiniportSend里的 irql是0(PASSIVE LEVEL),反复试了几次,有的时候是0,有的时候是2(DISPATCH LEVEL) 也就是在获取了spinlock后,当前cpu还是会被中断而再次进入MiniportSend,当然会 死锁了……看来ddk也不是完全正确,这里写出来,省得别人再走弯路 |
|
最新喜欢:![]() |
沙发#
发布于:2003-11-26 18:48
我也专门去琢磨做SPINLOCK,也发现在单CPU根本就没有任何作用.
|
|
|
板凳#
发布于:2003-11-27 23:00
NdisAcquireSpinlock把irql提升到2(dispatch level)了呀
|
|
地板#
发布于:2003-11-28 12:32
我用的是NdisDprAcquireSpinLock。既然ddk里面已经明确说了,是运行在dispatch level的,干嘛不用dpr呢
所以,就出错了,就郁闷了 |
|
地下室#
发布于:2003-11-28 15:23
即便是单CPU下使用SPIN_LOCK也还是要注意的,一是AcquieSpinlock会提升至DISPATCH_LEVEL,此时被保护的程序段只能使用非分页内存,否则一旦内存被换出去必然蓝屏,还有就是AcquireSpinlock和ReleaseSpinlock的间隔不能太长,时间长了可能就会有问题
|
|
5楼#
发布于:2008-05-24 19:37
引用第2楼arthurtu于2003-11-27 23:00发表的 : 根据我的测试结果,不是这样,NdisDprAcquireSpinLock也不能保证。 有没有手动提升IRQL的函数? |
|
|