Chinaunix
标题:
armv7的atomic_add实现,为什么不禁止中断
[打印本页]
作者:
arm-linux-gcc
时间:
2014-03-25 10:04
标题:
armv7的atomic_add实现,为什么不禁止中断
本帖最后由 arm-linux-gcc 于 2014-03-25 11:29 编辑
static inline void atomic_add(int i, atomic_t *v)
{
unsigned long tmp;
int result;
__asm__ __volatile__("@ atomic_add\n"
"1: ldrex %0, [%3]\n"
" add %0, %0, %4\n"
" strex %1, %0, [%3]\n"
" teq %1, #0\n"
" bne 1b"
: "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
: "r" (&v->counter), "Ir" (i)
: "cc");
}
ldrex/strex只能保证多个核一起访问同一个地址的时候具有排他性吧
如果core a在调用atomic_add时,在ldrex和strex之间core a发生了中断,而在core a上运行的中断处理程序刚好也要对同一个原子变量做atomic_add操作,那么就死锁了啊
作者:
humjb_1983
时间:
2014-03-25 10:38
arm的不懂~~
我看x86的代码中是加了LOCK的。
作者:
smalloc
时间:
2014-03-25 11:14
这个得自己编程考虑,如果中断程序会影响,就自己加了禁止中断了.
作者:
arm-linux-gcc
时间:
2014-03-25 11:20
回复
3#
smalloc
但是老的armv5的实现,是有关中断的啊
static inline int atomic_add_return(int i, atomic_t *v)
{
unsigned long flags;
int val;
raw_local_irq_save(flags);
val = v->counter;
v->counter = val += i;
raw_local_irq_restore(flags);
return val;
}
作者:
墙根下的水壶
时间:
2014-03-25 11:47
引入ldrex strex后,只要在ldrex和strex之间对应的原子变量被修改,则strex失败。那么多核环境下,保证了多核间的互斥,同样的,如果单核上,atomic_add执行中产生了中断,影响了对应的v->counter,则atomic_add这次的原子加操作失败了,便重新来过。这样保证了操作的原子性。至于如何判断中断是否影响了对应的v->counter,有的是只要产生总线操作就视为影响,有的则在硬件上处理更为细致。
总而言之,ldrex/strex机制避免了x86的锁总线操作,采用的是出错回退策略,可能对流水线性能有积极作用。
作者:
arm-linux-gcc
时间:
2014-03-25 11:56
回复
5#
墙根下的水壶
假如在进程上下文中ldrex执行之后、strex执行之前,同一个核就发生了中断,并且在中断处理中也对同一个原子变量atomic_add
那么在中断上下文的atomic_add就永远不能成功了啊,就一直在bne 1b,然后中断上下文的atomic_add就无法完成了,而进程上下文却由于被中断而无法做完strex,那么这个核就死锁了啊
作者:
墙根下的水壶
时间:
2014-03-25 12:44
回复
6#
arm-linux-gcc
实际上,中断的atomic_add是可以成功的,因为在他的ldrex和strex之间没有任何访存指令
作者:
arm-linux-gcc
时间:
2014-03-25 12:58
本帖最后由 arm-linux-gcc 于 2014-03-25 16:16 编辑
回复
7#
墙根下的水壶
我之前理解错了,新的ldrex来到时,会更新状态,于是中断上下文中的strex能成功,中断返回之后,进程上下文中的strex会失败
作者:
liuiang
时间:
2014-03-25 13:09
ARMv5只支持单核,不支持多核,基于这样的架构,要想实现原子操作,必须要锁中断。
对于你说的情况,ldrex和strex之间其他core或者中断终止了指令流,那么,中断或其他core中的 ldrex和strex 获得配对执行,而当程序流再次返回原始任务,strex执行就会失败,指令流会执行bne指令,进行重新执行尝试。
大多数RISC都是采用LL/SC结构完成原子操作,很少处理器像x86一样,提供lock前缀或直接的CAS原子指令。
作者:
smalloc
时间:
2014-03-25 14:37
之前有错,X86能直接操内存,所以一条指令搞定,不存在中断的问题.
上面的ARMV5版本因为多个指令,所以需要关中断.
出错尝试的说法是对的,这篇给了详细解释.
http://blog.chinaunix.net/uid-20543672-id-3262230.html
作者:
smalloc
时间:
2014-03-25 14:46
回复
8#
arm-linux-gcc
有意思的是,ldrex请求开始一个总线监控.
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2