int b = 1000;
b -= 20;
Is any of the above an atomic operation? What is an atomic operation in C?
int b = 1000;
b -= 20;
Is any of the above an atomic operation? What is an atomic operation in C?
It depends on the implementation. By the standard, nothing is atomic in C. If you need atomic ops you can look at your compiler's builtins.
It is architecture/implementation dependent.
If you want atomic operations, I think sig_atomic_t
type is standardized by C99, but not sure.
From the GNU LibC docs:
In practice, you can assume that int and other integer types no longer than int are atomic. You can also assume that pointer types are atomic; that is very convenient. Both of these are true on all of the machines that the GNU C library supports, and on all POSIX systems we know of.
This link seems to me to be on the right track in telling us what an atomic operation is in C:
http://odetocode.com/blogs/scott/archive/2006/05/17/atomic-operations.aspx
And it says, "...computer science adopted the term 'atomic operation' to describe an instruction that is indivisible and uninterruptible by other threads of execution."
And by that definition, the first line of code in the original question
int b=1000;
b-=20;
ought to be an atomic operation. The second could be an atomic operation if the CPU's instruction set includes an instruction to subtract directly from memory. The reason I think so is that the first code line would most likely require only one assembly (machine) instruction. And instructions either execute or not. I don't think any machine instruction can be interrupted in the middle.
At that same link, says, "If thread A is writing a 32-bit value to memory as an atomic operation, thread B will never be able to read the memory location and see only the first 16 of 32 bits written out." Seems that any single machine instruction cannot be interrupted in the middle, therefore would automatically be atomic between threads.
Incrementing and decrementing a number is not an atomic operation in C. Certain architectures support atomic incrementing and decrementing instructions, but there is no guarantee that the compiler would use them. You can look as an example at Qt reference counting. It uses atomic reference counting, on certain platforms it is implemented with platform-specific assembly code, and on the rest it is using a mutex to lock the counter.
If you're not incrementing or decrementing in a performance-critical part of your code, you'd simply use a mutex while doing it. If you're using it in performance-critical part of your code, you might want to try to rewrite your code in a way that doesn't use shared memory for this operation accessed from multiple places for this operation or use mutexes with higher granularity so that they don't affect the performance, or use assembly to ensure that the operation is atomic.
Quoting from ISO C89, 7.7 Signal handling <signal.h>
The type defined is
sig_atomic_t
which is the integral type of an object that can be accessed as an atomic entity, even in the presence of asynchronous interrupts.