How to perform atomic operations on Linux that work on x86, arm, GCC and icc?

29,049

Solution 1

Projects are using this:

http://packages.debian.org/source/sid/libatomic-ops

If you want simple operations such as CAS, can't you just just use the arch-specific implementations out of the kernel, and do arch checks in user-space with autotools/cmake? As far as licensing goes, although the kernel is GPL, I think it's arguable that the inline assembly for these operations is provided by Intel/AMD, not that the kernel has a license on them. They just happen to be in an easily accessible form in the kernel source.

Solution 2

Recent standards (from 2011) of C & C++ now specify atomic operations:

Regardless, your platform or compiler may not support these newer headers & features.

Solution 3

Darn. I was going to suggest the GCC primitives, then you said they were off limits. :-)

In that case, I would do an #ifdef for each architecture/compiler combination you care about and code up the inline asm. And maybe check for __GNUC__ or some similar macro and use the GCC primitives if they are available, because it feels so much more right to use those. :-)

You are going to have a lot of duplication and it might be difficult to verify correctness, but this seems to be the way a lot of projects do this, and I've had good results with it.

Some gotchas that have bit me in the past: when using GCC, don't forget "asm volatile" and clobbers for "memory" and "cc", etc.

Solution 4

There is a patch for GCC here to support ARM atomic operations. WIll not help you on Intel, but you could examine the code - there is recent kernel support for older ARM architectures, and newer ones have the instructions built in, so you should be able to build something that works.

http://gcc.gnu.org/ml/gcc-patches/2011-07/msg00050.html

Solution 5

Boost, which has a non intrusive license, and other frameworks already offer portable atomic counters -- as long as they are supported on the target platform.

Third party libraries are good for us. And if for strange reasons your company forbid you from using them, you can still have a look at how they proceed (as long as the licence permit it for your use) to implement what your are looking for.

Share:
29,049
Artyom
Author by

Artyom

I'm an author of several FOSS projects: CppCMS - High performance, MVC C++ Web Development Framework. Boost.Locale - High quality localization tools for C++ (currently waits for review for Boost) BiDiTeX - bidirectional support of Hebrew in LaTeX. CppDB - SQL Connectivity library for C++ (independent part of CppCMS Project)

Updated on July 09, 2022

Comments

  • Artyom
    Artyom almost 2 years

    Every Modern OS provides today some atomic operations:

    • Windows has Interlocked* API
    • FreeBSD has <machine/atomic.h>
    • Solaris has <atomic.h>
    • Mac OS X has <libkern/OSAtomic.h>

    Anything like that for Linux?

    • I need it to work on most Linux supported platforms including: x86, x86_64 and arm.
    • I need it to work on at least GCC and Intel Compiler.
    • I need not to use 3rd par library like glib or qt.
    • I need it to work in C++ (C not required)

    Issues:

    • GCC atomic builtins __sync_* are not supported on all platforms (ARM) and are not supported by the Intel compiler.
    • AFAIK <asm/atomic.h> should not be used in user space and I haven't successfully used it at all. Also, I'm not sure if it would work with Intel compiler.

    Any suggestions?

    I know that there are many related questions but some of them point to __sync* which is not feasible for me (ARM) and some point to asm/atomic.h.

    Maybe there is an inline assembly library that does this for GCC (ICC supports gcc assembly)?

    Edit:

    There is a very partial solution for add operations only (allows implementing atomic counter but not lock free-structures that require CAS):

    If you use libstc++ (Intel Compiler uses libstdc++) then you can use __gnu_cxx::__exchange_and_add that defined in <ext/atomicity.h> or <bits/atomicity.h>. Depends on compiler version.

    However I'd still like to see something that supports CAS.

  • Tim Post
    Tim Post over 14 years
    I've ended up with asm volatile not being volatile, though I suspect that phenomenon is not limited just to inline assembly.
  • josesuero
    josesuero over 14 years
    Which Boost library includes these?
  • Luc Hermitte
    Luc Hermitte over 14 years
  • Artyom
    Artyom over 14 years
    (a) Boost falls back to pthreads frequently, in fact for ARM it would use pthreads. (b) atomic_counters provide only inc/dec operations that are fine for reference counting but they are too weak. If you need something like atomic linked list where you need operations like CAS.
  • Artyom
    Artyom over 14 years
    "And if for strange reasons your company forbid you from using them" I do not forbid I just prefer not to use 3rd part libraries to reduce an about of dependencies to build certain project.
  • Jens Gustedt
    Jens Gustedt over 13 years
    the problem with the gcc primitives, is that in some versions they are in fact available, but there is no feature test macro to test for them.
  • Hasturkun
    Hasturkun almost 11 years
    IIRC, for GCC, this might require use of libatomic.
  • Isaac
    Isaac over 8 years
    @Hasturkun: Which version of GCC? Is that still the case for the recent GCC releases?
  • Hasturkun
    Hasturkun over 8 years
    @Isaac: According to the GCC Wiki on the C++11 memory model, as of GCC 4.7 libatomic may be required when lock-free instructions aren't available. GCC 4.8 includes libatomic in its source tree.