[Openmcl-devel] [openmcl-devel] atomic-incf
Gary Byers
gb at clozure.com
Thu Oct 15 14:23:31 PDT 2009
On Thu, 15 Oct 2009, David L. Rager wrote:
> Hello Gary and Co.,
>
> Two questions about atomic-incf:
>
> (1) It's not showing up as external for me (release 1.3). Is it
> reasonable to make it external? Is there a reason that it's not
> exposed other than just not wanting to make too many promises about an
> API?
Laziness and sloth also factor into it.
>
> (2) By "atomic", does it mean that no other threads can read/write
> that variable during the actual increment? I'm not worried about all
> the code that wraps the increment (perhaps it checks the type of the
> argument, etc.). I'm just trying to make sure the increment itself is
> thread-safe.
Incrementing a memory location that contains a fixnum by 1 (and ignoring
overflow) is something like:
(load reg @loc) ; reg <- contents-of (loc)
(add reg #fixnum-one) ; reg <- reg+1
(store reg @loc) ; contents-of (loc) <- reg
Even if it's implemented as a single CISCy instruction, there's likely
to be a similar sequence of independent read, modify, and write
operations at some microarchitectural level. If two or more threads
are running concurrently, those operations could be interleaved; if
"loc" contains 0 and two threads try to increment it by one, then we
could have something like:
(load reg @loc) ; on thread 1, reg = 1
(add reg #fixnum-one) ; on thread 1, reg = 1
(load reg @loc) ; on thread 2, reg = 0
(add reg #fixnum-one) ; on thread 2, reg = 1
(store reg @loc) ; on thread 2, contents-of (loc) = 1
(store reg @loc) ; on thread 1, contents-of (loc) = 1
and each thread would think that it'd successfully incremented "loc"
from 0 to 1. ATOMIC-INCF basically tries to guarantee that the
read-modify-write sequence happens atomically.
>
> My guess is that atomic-incf calls the X86 instruction that locks the
> bus for a particular memory address and increments that variable.
>> From looking at the implementation in x86-misc.lisp, it looks like it
> does indeed perform a lock on a memory address, performs a compare and
> exchange with an atomicity guarantee, and then loops back to the
> beginning of the function if that compare and exchange failed. In the
> PPC implementation, it looks like the lrarx and strcx instructions
> combine to also provide an atomic increment.
I think that we could actually implement it as
(lock)
(addq ($ fixnumone) (@ loc))
or
(movq increment-by (% reg))
(lock)
(addq (% reg) (@ loc))
on x86; we actually do a similar compare-and-swap loop on both
architectures.
(If anyone's curious, "lrarx" and "strcx" are macros that expand
into word-size specific PPC instructions, e.g. "lwarx/stwcx." on
32-bit PPC, "ldarx/swdcx." on PPC64.)
>
> Thanks,
> David
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>
More information about the Openmcl-devel
mailing list