From what I understand of atomics, they are special assembly instructions which guarantee that two processors in an SMP system cannot write to the same memory region at the same time. For example in PowerPC an atomic increment would look something like:
retry:
lwarx r4, 0, r3 // Read integer from RAM location r3 into r4, placing reservation.
addi r4, r4, 1 // Add 1 to r4.
stwcx. r4, 0, r3 // Attempt to store incremented value back to RAM.
bne- retry // If the store failed (unlikely), retry.
However this does not protect the four instructions from begin preempted by an interrupt, and another task being scheduled in. To protect from preemption you need to do an interrupt-lock before entering the code.
From what I can see of C++ atomics, they seem to be enforcing locks if needed. So my first question is -
- Does the C++ standard guarantee no preemption will happen during an atomic operation? If so, where in the standard can I find this?
I checked the atomic<int>::is_always_lock_free
on my Intel PC, and it came true
. With my assumption of the above assembly block, this confused me. After digging into Intel assembly (which I am unfamiliar with) I found lock xadd DWORD PTR [rdx], eax
to be happening. So my question is -
- Do some architectures provide atomic related instructions which guarantee no-preepmtion? Or is my understanding wrong?
Finally I was wondering about the compare_exchange_weak
and compare_exchange_strong
semantics -
- Does the difference lie int the retry mechanism or is it something else?
EDIT: After reading the answers, I am curious about one more thing
- The atomic member function operations
fetch_add
,operator++
etc. are they strong or weak?