Tim Hockin <thockin(a)hockin.org> writes:
On Sun, Aug 17, 2003 at 12:56:09PM -0500, Jack
O'Quin wrote:
I am looking for a good set of portable, supported atomic.h-style
primitives for userspace applications. I am not especially interested
in the low-level functions defined in <asm/atomic.h>. I really want
something more powerful like the kernel's compare_and_swap(),
cmpxchg(), test_and_set(), atomic_inc_and_return(), or fetch_and_add()
These are intrinsically platform specific.
The underlying instructions are platform-specific, but these functions
*can* be implemented efficiently on most (but not all) platforms that
Linux programs are likely to see. Grepping linux-2.6.0-test3/include
for cmpxchg() yields...
$ grep -l cmpxchg asm-*/system.h
asm-alpha/system.h
asm-i386/system.h
asm-m68knommu/system.h
asm-ppc/system.h
asm-ppc64/system.h
asm-s390/system.h
asm-sparc64/system.h
asm-x86_64/system.h
That's quite a few platforms that appear to support this useful
compare and exchange function.
For atomic_inc_return(), the results are more impressive...
$ grep -l atomic_inc_return asm*/atomic.h /dev/null
asm-alpha/atomic.h
asm-cris/atomic.h
asm-h8300/atomic.h
asm-ia64/atomic.h
asm-m68knommu/atomic.h
asm-mips/atomic.h
asm-parisc/atomic.h
asm-ppc/atomic.h
asm-ppc64/atomic.h
asm-s390/atomic.h
asm-sh/atomic.h
asm-sparc/atomic.h
asm-sparc64/atomic.h
asm-v850/atomic.h
It seems a shame there is no i386 version of atomic_inc_return(). I
don't know x86 assember well enough to understand why. Does anyone
know of an i386 version of this function? Or, if not, know why it's
not possible? I think it could be programmed out in C using
compare_and_swap() as a primitive.
(*) glibc
seems to have a good set of functions internally
AFAICT, these are for the library's own use, not part of the
supported external interface. I'll investigate further.
It sure would be nice if glibc exposed an atomic API. I dunno how much you
can do as a user, though. Can non-privileged tasks run LOCKed instructions
on x86? How about other architectures?
Yes for x86. LOCK is an x86 instruction. Other architectures solve
these problems in various ways.
For example, PowerPC uses lwarx and stwcx. The lwarx loads a word and
reserves its cache line. Then, stwcx conditionally stores the word if
the cache line is still reserved. If another processor has stolen the
cache entry the store does not occur and a condition code is set
indicating the failure. These are not privileged instructions.
Similarly, the S/390's `cs' instruction (compare and swap) is not a
privileged operation. IIRC, this instruction dates back to the IBM
360. Machine designers have understood the importance of user-mode
synchronization ops for at least the last 30 or 40 years. I believe
this was originally because databases use them, and databases sell a
*lot* of hardware. Many database programmers are frustrated kernel
developers who insist on programming "right down to the bare metal".
Lock performance is often a critical factor in database throughput.
Here are the files containing compare_and_swap() references in
linuxthreads/sysdeps subdirectories. All are user-level functions.
grep -lIr compare_and_swap * /dev/null
alpha/pt-machine.h
arm/pt-machine.h
cris/pt-machine.h
hppa/pt-machine.h
i386/pt-machine.h
i386/i686/pt-machine.h
ia64/pt-machine.h
m68k/pt-machine.h
mips/pt-machine.h
powerpc/pspinlock.c
powerpc/powerpc32/pt-machine.h
powerpc/powerpc64/pt-machine.h
pthread/bits/pthreadtypes.h
s390/s390-32/pt-machine.h
s390/s390-64/pt-machine.h
sh/pt-machine.h
sparc/sparc32/pt-machine.h
sparc/sparc64/pt-machine.h
x86_64/pt-machine.h
According to the comments in i386/pt-machine.h, compare_and_swap()
only works on 486 and above. That is adequate for my purposes.
--
Jack O'Quin
Austin, Texas, USA