richardtech (richardtech) wrote,

Atomic integer operations

A short while ago I was bitten by the lack of support for atomic integer operations in Linux. Whilst the kernel implements exactly the operations I need for all the supported operating systems (in the header files included by asm/atomic.h), including those files from userland code is apparently not allowed. On Debian based systems it works fine and no warning is reported, but on Redhat based systems (and presumably others, too), a warning message is displayed ("Using kernel header in userland program. BAD!"), and my compilation fails (because I use the -Werror flag to ensure clean builds).

Because I was in a hurry, and couldn't find a better solution immediately, I didn't look into the problem deeply, and just wrote a couple of assembly functions to perform atomic integer operations on the platform I was working on at the time, and made a mental note to look for a proper solution soon.

I spent most of yesterday (when I wasn't out in the garden), looking into this.

  • On Windows, programmers can use the InterlockedIncrement() and InterlockedDecrement() to perform the atomic integer manipulations I wanted.
  • On MacOSX, programmers can use OSAtomicIncrement32Barrier() and OSAtomicDecrement32Barrier() to perform the atomic integer manipulations I wanted.
  • On BSD, programmers can use atomic_add() and atomic_cmpset() (though apparently, according to the atomic(9) manpage, "The current set of atomic operations do not necessarily guarantee atomicity across multiple processors.", though it's guaranteed for i386, and had I written the assembly myself I'd probably have missed the issue which makes it not work on ia64.)
  • On Linux, since you're not allowed to use the kernel header files, there is no available solution.
After some searching, I found a (rather flamey) 18 month old thread on the linux kernel development mailing list discussing this. To summarise roughly, the kernel headers are currently not in a state in which they can safely be included from userland (eg, see and the kernel developers don't want to be tied to providing any more APIs than they have to, so they refuse to support any inclusion of kernel headers from userland - except for a few specific cases which don't include the atomic modification code. Fair enough so far.

However, things aren't quite that simple: one post mentions that it's not always possible to implement atomic operations simply in userland (, and another post (from Linus) mentions that including the headers from an application might require the application to be licensed under the GPL (since the code is in inline functions, and thus including these headers involves actually incorporating code into the application, as opposed to simply linking to a system call). (Unfortunately, I can't find a reference to that post now, so I may have mis-summarised.)

This is really frustrating for application developers on Linux: there is some fairly good code which, with a little work and maintainance, could provide the neccessary atomic operations. If it weren't for the legal questions, and the flamey nature of kernel development, I might try and pull that code into shape and persuade the kernel developers to add the atomic operations to the small set of headers which can be included from userland. Instead, I'm putting together a library which will implement atomic operations (or link to the appropriate system defined ones) with a standard, cross platform, interface. I'll add a post in a while to let you know how I get on with that.

  • Post a new comment


    default userpic