用原子交换实现原子增量? [英] Implement atomic increment using atomic swap?
问题描述
假设我写(组装)code,对于CPU的唯一原子操作是无条件交换 - 无LL / SC,没有比较和交换,只是普通的交换。 (一个ARM9会是这样的野兽的一个例子。)是否有使用交换操作执行原子递增/递减操作的方法吗?
Suppose I'm writing (assembly) code for a CPU whose only atomic operation is an unconditional swap -- no LL/SC, no compare-and-swap, just plain swap. (An ARM9 would be an example of such a beast.) Is there a way to perform atomic increment/decrement operations using the swap operation?
有是一个相对容易的答案,这就是用交换来构建一个自旋锁,并用它来提供围绕普通的增量和减量的重要部分。但似乎笨重,而且我知道它可以在不锁,如果CAS或LL / SC都可以完成。那么,我真的不知道是,如果有一种方法可以做到这一点,而无需使用锁。
There is a relatively easy answer, which is to use the swap to build a spinlock, and use that to provide a critical section around ordinary increment and decrement. But that seems clunky, and I know it can be done without a lock if CAS or LL/SC are available. So what I'm really wondering is if there's a way to do it without using a lock.
推荐答案
我想不出另一种方式来做到这一点,仅仅是因为你需要在两个交换和比较来检测,如果你被允许继续进行。如果您还没有一个比较并交换命令,你将会有一个循环交换来实现它和比较,是这样的:
I can't think of another way to do it, simply because you need to both swap and compare to detect if you're allowed to proceed. If you don't have a compare-and-swap command, you'll have to implement it with a looping swap and compare, something like:
; Emulate atomic add/sub with atomic swap.
; On entry:
; r0 contains address of variable
; r1 contains value to add or subtract.
mutex: defw 0 ; mutual exclusion semaphore (0=free, 1=busy).
chng: push r2 ; save variables.
ld r2,1 ; claiming value.
spin: swap r2,(mutex) ; atomic swap (sounds like a good name for a band).
bnz spin ; loop until you have it.
add (r0),r1 ; emulated atomic change.
swap r2,(mutex) ; free mutex for everyone else.
pop r2 ; restore registers.
ret
这是唯一真正klunky如果你在很多你的code的地方这样做。我经常发现,隔离'klunky'code到(如上)功能使得它远不如klunky既然你那么有很多code段看起来像简单得多的结束:
It's only really klunky if you're doing it in a lot of places in your code. I've often found that isolating 'klunky' code to a function (like above) makes it far less klunky since you then end up with lots of code segments looking like the much simpler:
myvar: defw 0
: : : : :
ld r0,myvar
ld r1,1 ; increment
call chng
或者,如果你希望你的code更简单,提供单独的增量
和 DECR
功能:
; Emulate atomic incr/decr with emulated atomic change.
; On entry:
; r0 contains address of variable
incr: push r1 ; save registers.
ld r1,1 ; increment.
call chng ; do it.
pop r1 ; restore registers.
ret
decr: push r1 ; save registers.
ld r1,-1 ; decrement.
call chng ; do it.
pop r1 ; restore registers.
ret
那么你的code序列变成:
Then your code sequences become:
ld r0,myvar
call incr
或者,如果你能做到的宏,一个更简单的:
or, if you can do macros, an even simpler:
atincr: defm ; do this once to define macro
ld r0,&1
call incr
endm
atincr myvar ; do this in your code, as much as you like.
这篇关于用原子交换实现原子增量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!