Home > Software design >  is `int` an atomic type?
is `int` an atomic type?

Time:12-18

Quoting gnu:

In practice, you can assume that int is atomic. You can also assume that pointer types are atomic; that is very convenient. Both of these assumptions are true on all of the machines that the GNU C Library supports and on all POSIX systems we know of.

How is this possible? All examples I've seen related to locks are made with an int counter, like this https://www.delftstack.com/howto/c/mutex-in-c/.

CodePudding user response:

This text in the glibc manual is only relevant for things like volatile sig_atomic_t being safe between a thread and its signal handler. They're guaranteeing that volatile int will work that way, too, in GNU systems. Note the context you omitted:

To avoid uncertainty about interrupting access to a variable, you can use a particular data type for which access is always atomic: sig_atomic_t. Reading and writing this data type is guaranteed to happen in a single instruction, so there’s no way for a handler to run “in the middle” of an access.

This says nothing about atomicity wrt. other threads or concurrency. An interrupt handler takes over the CPU and runs instead of your code. Asynchronously at any point, but the main thread and its signal handler aren't both running at once (especially not on different CPU cores).


For threading, atomicity isn't sufficient, you also need a guarantee of visibility between threads (which you can get from _Atomic int with memory_order_relaxed), and sometimes ordering which you can get with stronger memory orders.

See the early parts of Why is integer assignment on a naturally aligned variable atomic on x86? for more discussion of why a C type having a width that is naturally atomic on the target you're compiling for is not sufficient for much of anything.

You sometimes also need RMW atomicity, like the ability to do an atomic_fetch_add such that if 1000 such =1 operations happen across multiple threads, the total result will be like =1000. For that you absolutely need compiler support (or inline asm), like C11 _Atomic int. Can num be atomic for 'int num'?

The guarantee that int is atomic means atomic_int should always be lock-free, and cheap, but it absolutely does not mean plain int is remotely safe for data shared between threads. That's data-race UB, and even if you use memory barriers like GNU C asm("" ::: "memory") to try to get the compiler to not keep the value in a register, your code can break in lots of interesting ways that are more subtle than some of the obvious breakage mechanisms. See Who's afraid of a big bad optimizing compiler? on LWN for some caveats about doing that in the Linux kernel, where they use volatile for atomicity.

(Fun fact: GNU C at least de-facto gives pure-load and pure-store atomicity with volatile int64_t on 64-bit machines, unlike with plain int64_t. ISO C doesn't guarantee even that for volatile, which is why the Linux kernel depends on being compiled with GCC or maybe clang.)

  • Related