+ -
当前位置:首页 → 问答吧 → 为什么原子操作能称为原子操作?

为什么原子操作能称为原子操作?

时间:2010-04-11

来源:互联网

static inline int atomic_dec_and_test(atomic_t *v)
{
        unsigned char c;

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


这里面的汇编代码有两句,那么在执行第一句的时候发生了中断,那么岂非就是不原子操作了?

作者: etoux   发布时间: 2010-04-11

本帖最后由 smalloc 于 2010-04-11 13:52 编辑

http://linux.chinaunix.net/bbs/v ... p;extra=&page=3

这么说来原子变量仅仅只保证第一个指令(即内存变量中的值减1)的原子性,这样不会产生计数和操作次数间的误差。
但是不保证计数和返回结果的一致性。
比如在多处理器,或者多任务,或者一个中断内与一个中断外,这些情况下对同一个原子变量的操作,其结果并不能保证一致性。

作者: smalloc   发布时间: 2010-04-11

回复 smalloc


    我想问一问,这个LOCK锁住总线是怎么样的体现,能为我讲讲吗?

作者: etoux   发布时间: 2010-08-21

(仔细看了看这段话仿佛明白了)
现在解释如下,首先说一点,任何一条汇编指令都是在一个不可分割的指令周期内完成的,也就是说,只有在指令周期内的最后一个点才回查询是否有中断发生了。现在说说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的真实的数值.

作者: etoux   发布时间: 2010-08-21