1

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/.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • The tutorial is sticking to the guarantees in the C standard, which don't make the assumptions that the GNU C library does. – Barmar Dec 17 '22 at 19:31
  • 1
    "Int is an atomic type?" --> No, not certainly. – chux - Reinstate Monica Dec 17 '22 at 19:37
  • 1
    The GNU doc is saying that no actual processor will let you see a partial write to an int or pointer. That may be true, but it's still undefined behaviour if you have a data race, ie if you read and write an int in different threads without synchronization between them, and the days one can believe in safe undefined behaviour are gone. – Paul Hankin Dec 17 '22 at 19:42

1 Answers1

4

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.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Somewhat interesting that this effectively rules out support for 8 bit CPUs regardless of address space constraints simply because loads and stores of int would be 2 instructions unless there is something like a load-pair/store-pair instruction – Homer512 Dec 21 '22 at 10:58
  • @Homer512: Yeah, I noticed that to. But note that this is a *glibc* guarantee, not GCC. GCC supports some 8-bit CPUs, including AVR, but not Unix or a full GNU system on them. – Peter Cordes Dec 21 '22 at 11:04