免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 9566 | 回复: 20
打印 上一主题 下一主题

中断atomic操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-04-10 12:19 |只看该作者 |倒序浏览
本来说atomic操作都是原子的,但是我真的是弄不清楚,从atomic_inc_and_test的定义来看,他怎么会是不可中断的呢,定义如下:
static __inline__ int atomic_inc_and_test(atomic_t *v)
{
        unsigned char c;

        __asm__ __volatile__(
                LOCK_PREFIX "incl %0; sete %1"
                :"+m" (v->counter), "=qm" (c)
                : : "memory");
        return c != 0;
}

在smp中lock_prefiX被扩展为空,比如说:当incl %0执行完之后,如果此时发生了中断,那么我认为这个时候就有可能导致系统的不一致。请问在单处理机上怎么样来保证原子操作的真正的实现,还是压根就没有必要。同时为什么在多处理机上就扩展lock_prefiX,lock_prefiX到底是起到一个什么样的作用?谢谢了

[ 本帖最后由 wojiaohesen 于 2008-4-10 21:45 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-04-10 13:43 |只看该作者
UP上没必要, 因为单条指令不会被中断 ── 中断的发生,只能等待到 一条指令执行完毕,这是CPU保证了的。

SMP下有必要,因为要防止其他CPU同时访问。 锁了总线, 中断也得等待。

//FIXME

论坛徽章:
0
3 [报告]
发表于 2008-04-10 14:07 |只看该作者
我也困惑,但是incl %0; sete %1是两条指令啊,而且atomic_inc_and_test整个函数内部的指令好象还多。。

论坛徽章:
0
4 [报告]
发表于 2008-04-10 18:57 |只看该作者
我猜是因為中斷會保存標誌寄存器
sete就算被中斷也可以得到正確值吧....
希望高手給個確切解釋

论坛徽章:
0
5 [报告]
发表于 2008-04-10 20:34 |只看该作者
原帖由 haohao06 于 2008-4-10 18:57 发表
我猜是因為中斷會保存標誌寄存器
sete就算被中斷也可以得到正確值吧....
希望高手給個確切解釋

我认为这个是正解

论坛徽章:
0
6 [报告]
发表于 2008-04-10 21:08 |只看该作者
但是问题是如果第一条指令执行完之后,如果此时发生了中断,那是不是会产生内存不一致的问题.

论坛徽章:
0
7 [报告]
发表于 2008-04-10 21:18 |只看该作者

回复 #2 albcamus 的帖子

我觉得这个就有问题,不论在up还是smp上,单条指令都不会被中断,中断只有在一个指令周期的最后时间才能被cpu探测到.
所以现在的问题是,如果当第一个指令执行完之后的话,并且v是个全局变量,那么这个时候是不是回导致系统不一致的现象出现,本来觉得这个函数应该是不可重入的,但是从它的技术上来说,应该是可重入的.
望高手给点解释.

论坛徽章:
0
8 [报告]
发表于 2008-04-10 21:30 |只看该作者
我的意思是,如果v此时是个全局变量.当执行完第一条指令之后,然后中断发生,如果此时发生抢占的话,并且被抢占的进程恰好也需要修改该变量,并且使用的是指令atomic_dec_and_test,当执行流重新回到被中断的进程的时候,这个时候看起来已经发生了内存不一致的现象啊 .
希望能给更清楚的解释,谢谢

论坛徽章:
0
9 [报告]
发表于 2008-04-10 21:34 |只看该作者
还有就是LOCK_PREFIX 到底是锁定什么,以及为什么这么做?

论坛徽章:
0
10 [报告]
发表于 2008-04-10 22:08 |只看该作者
还是我自己弄懂,现在解释如下,首先说一点,任何一条汇编指令都是在一个不可分割的指令周期内完成的,也就是说,只有在指令周期内的最后一个点才回查询是否有中断发生了。现在说说lock_prefix的作用,首先想一想,因为任何的操作都在cpu的内部进行完成,所以如果想对变量v进行操作的话,那么在一个inc指令周期内,实际上cpu还是需要从内存总读出v的数值,然后对v处理之后,再写回到内存中去.这里需要注意的一个问题就是inc指令周期中,实际上发生了多次的对内存的进行访问,而这些对内存进行的访问实际上在地址总线上并不是原子操作的,也就是说.如果存在多个cpu的话,那么另外的cpu完全可以在该inc读出v的数值之后,另外的cpu这个时候就可以占用地址总线,从中读出v的数值,而这个时候,当前的cpu当修改v的数值之后,再回写到内存中,这个时候实际上就已经导致了内存的不一致的问题.因为另外的cpu的数值和真实的数值已经是不一样了。而lock_prefix的作用就是使一个指令,例如incl这样的操作在地址总线上也是原子操作的.也就是这个指令会一直的站用着地址总线,直到把v的数值写到内存中.而当地址总线锁定的时候,别的cpu压根就不能访问cpu.所以这样就从总线的站用上保证了原子.
还有就是可能有人认为在incl和sete之间不是可以被中断的吗?实际上确实是可以被中断的.但是需要清楚的是.该条指令只是说本次操作的结果是不是1,而不是用来说变量v的数值是不是0.如果你需要根据该数值进行一些操作的话,那么该函数的结果并不代表当前的变量v的真实的数值.

呵呵.解释的不知道对不对?欢迎指正
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP