Poni
Poni

Reputation: 11317

Does a CPU assigns a value atomically to memory?

A quick question I've been wondering about for some time; Does the CPU assign values atomically, or, is it bit by bit (say for example a 32bit integer).
If it's bit by bit, could another thread accessing this exact location get a "part" of the to-be-assigned value?

Think of this:
I have two threads and one shared "unsigned int" variable (call it "g_uiVal").
Both threads loop.
On is printing "g_uiVal" with printf("%u\n", g_uiVal).
The second just increase this number.
Will the printing thread ever print something that is totally not or part of "g_uiVal"'s value?

In code:

unsigned int g_uiVal;

void thread_writer()
{
 g_uiVal++;
}
void thread_reader()
{
 while(1)
  printf("%u\n", g_uiVal);
}

Upvotes: 9

Views: 548

Answers (7)

Chris O
Chris O

Reputation: 5037

Considering modern microprocessors (and ignoring microcontrollers), the 32-bit assignment is atomic, not bit-by-bit.

However, now completely off of your question's topic... the printing thread could still print something that is not expected because of the lack of synchronization in this example, of course, due to instruction reordering and multiple cores each with their own copy of g_uiVal in their caches.

Upvotes: 0

Chris Dodd
Chris Dodd

Reputation: 126243

POSIX defines the special type sig_atomic_t which guarentees that writes to it are atomic with respect to signals, which will make it also atomic from the point of view of other threads like you want. They don't specifically define an atomic cross-thread type like this, since thread communication is expected to be mediated by mutexes or other sychronization primitives.

Upvotes: 0

myron-semack
myron-semack

Reputation: 6425

You said "bit-by-bit" in your question. I don't think any architecture does operations a bit at a time, except with some specialized serial protocol busses. Standard memory read/writes are done with 8, 16, 32, or 64 bits of granularity. So it is POSSIBLE the operation in your example is atomic.

However, the answer is heavily platform dependent.

  • It depends on the CPU's capabilities. Can the hardware do an atomic 32-bit operation? Here's a hint: If the variable you are working on is larger than the native register size (e.g. 64-bit int on a 32-bit system), it's definitely NOT atomic.
  • It depends on how the compiler generates the machine code. It could have turned your 32-bit variable access into 4x 8-bit memory reads.
  • It gets tricky if the address of what you are accessing is not aligned across a machine's natural word boundary. You can hit a a cache fault or page fault.

It is VERY POSSIBLE that you would see a corrupt or unexpected value using the code example that you posted.

Your platform probably provides some method of doing atomic operations. In the case of a Windows platform, it is via the Interlocked functions. In the case of Linux/Unix, look at the atomic_t type.

Upvotes: 1

Puppy
Puppy

Reputation: 146940

Don't forget that the compiler assumes single-thread when optimizing, and this whole thing could just go away.

Upvotes: 0

mfeingold
mfeingold

Reputation: 7154

To add to what has been said so far - another potential concern is caching. CPUs tend to work with the local (on die) memory cache which may or may not be immediately flushed back to the main memory. If the box has more than one CPU, it is possible that another CPU will not see the changes for some time after the modifying CPU made them - unless there is some synchronization command informing all CPUs that they should synchronize their on-die caches. As you can imagine such synchronization can considerably slow the processing down.

Upvotes: 0

crazyscot
crazyscot

Reputation: 11989

Depends on the bus widths of the CPU and memory. In a PC context, with anything other than a really ancient CPU, accesses of up to 32 bit accesses are atomic; 64-bit accesses may or may not be. In the embedded space, many (most?) CPUs are 32 bits wide and there is no provision for anything wider, so your int64_t is guaranteed to be non-atomic.

Upvotes: 4

Evan Teran
Evan Teran

Reputation: 90442

I believe the only correct answer is "it depends". On what you may ask?

Well for starters which CPU. But also some CPUs are atomic for writing word width values, but only when aligned. It really is not something you can guarantee at a C language level.

Many compilers offer "intrinsics" to emit correct atomic operations. These are extensions which act like functions, but emit the correct code for your target architecture to get the needed atomic operations. For example: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html

Upvotes: 3

Related Questions