5

I assume that on a 32-bit device like the iPhone, assigning a short float is an atomic, thread-safe operation. I want to make sure it is. I have a C function that I want to call from an Objective-C thread, and I don't want to acquire a lock before calling it:

void setFloatValue(float value) {
    globalFloat = value;
}
iter
  • 4,171
  • 8
  • 35
  • 59

3 Answers3

5

In 32-bit ARM, the function above will be compiled to

ldr r2, [pc, #0x??]  ; to retrieve the address of globalFloat
str r0, [r2]         ; store value into globalFloat

As there are 2 instructions, and the CPU is free to perform anything between them, but only the second instruction str r0, [r2] affects memory. Unless globalFloat is unaligned, the CPU can perform single-copy atomic write to it.

The assignment can be non-atomic when the global pointer is unaligned. It is also non-atomic if you are writing to a larger structure e.g. CGRect.

Being atomic is not enough for thread safety. Due to caching and instruction reordering, your change may not be visible to other CPU cores. You may need to insert an OSMemoryBarrier() to "publish" the change.

Atomic operations are usually interesting when it involves compound operations (e.g. globalFloat += value). You may want to check out the built-in OSAtomic library for it.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • But this is still "kinda sorta atomic", in that the actual write to the global state is a single instruction, so nobody looking at globalFloat can ever see it in an in-between state. – unwind Mar 31 '10 at 07:02
  • 2
    There isn't one for assignment. – Andreas Bonini Mar 31 '10 at 07:02
  • @unwind: that's true of any store instruction. The in-between state here is after it's read and before it's written, when the variable physically exists in two places (memory and register) at once. – Potatoswatter Mar 31 '10 at 07:06
  • @Potatoswatter: I don't think so. It's possible to imagine architectures where there's a single instruction that stores a value that is larger than the external data bus. This instruction would need to be split into multiple bus transactions, so if you look at memory it will be partially updated, with intermediate states visible during entire cycles. – unwind Mar 31 '10 at 07:12
  • 5
    It isn't kind sort atomic. It is completely atomic. The first instruction doesn't interact with the value at all, it just loads its address into r2. @Potatoswatter, the question is not whether the variable exists in two or more places at once (the same can be said of char), but whether the value can be partially written to the memory location by one thread when another thread attempts to read it. This can never happen in the above code. – Marcelo Cantos Mar 31 '10 at 07:19
  • 1
    @unwind, @Marcelo: I'd be surprised if any native datatype of the iPhone processor takes more than one memory transaction to store. (Double, really?) Atomicity in programming (and most hardware specifications) refers to read-modify-write. You can't synchronize threads without that, and OP asks about threads. – Potatoswatter Mar 31 '10 at 10:23
3

Yes, it will be atomic. On a 32-bit architecture, any store operation on a primitive datatype that is 32-bits or smaller (char, short, int, long, float, etc.) will be atomic.

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
1

There is more to your question than just atomicity. Even if a write is atomic, there is no guarantee that another thread will see the change without some kind of memory barrier. This probably isn't a problem with current iPhones because they only have one cpu, but it can be a problem on desktop machines.

See:

Community
  • 1
  • 1
EricS
  • 9,650
  • 2
  • 38
  • 34