4

I wonder if I could read or write shared int value without locking on mips cpu (especially Amazon or Danube). What I mean is if such a read or write are atomic (other thread can't interrupt them). To be clear - I don't want to prevent the race between threads, but I care if int value itself is not corrupted.

Assuming that the compiler aligns all ints at the boundaries of cpu word, it should be possible. I use gcc (g++). Tests also shows that it seems work correctly. But maybe someone knows it for sure?

oo_olo_oo
  • 2,815
  • 5
  • 28
  • 25
  • They can be atomic, however, if it's beyond half the main register size, it can not, see my assembly links. Unless you use the atomically defined functions which will take that into account and lock. – sfossen Mar 27 '09 at 14:11
  • danube and amazon are MIPS32, R10000 is MIPS64, reference in @sysrqb answer is referencing the MIPS64, so my you are not guaranteed atomic writes. – sfossen Mar 27 '09 at 16:52
  • use "objdump -d filename" and find the function in question to check/verify. Atomic operations will not usually be used by default. – sfossen Mar 27 '09 at 18:33

4 Answers4

7

Use gcc's builtin atomic operations and you'll get warnings if they're not supported: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

It looks like combinations of addition/subtraction and testing (at least) are possible on the hardware: http://rswiki.csie.org/lxr/http/source/include/asm-mips/atomic.h

rmmh
  • 6,997
  • 26
  • 37
4

Depends on the operation. Having stared at enough disassembled programs in MIPS, I know that only some operations are atomic.

assignment of a new value could be 1 op or more, you'd have to look at the assembly.

eg:

x = 0; // move $a0, $0


x = 0x50000; // lui $a0, 0x0005


x = 0x50234; // lui $a0, 0x0005
             // ori $a0, 0x0234

MIPS assembley reference or here

see here to see danube and amazon are MIPS32, which my example covers, and therefore not all 32bit integer immediate can be written atomically.

see R10000 in above posting is MIPS64. Since a 32bit value would be half the register size, it could be an atomic load/write.

sfossen
  • 4,774
  • 24
  • 18
  • what compiler did you use to compile your example? – oo_olo_oo Mar 27 '09 at 17:58
  • Isn't int value 64bit on MIPS64 platform? – oo_olo_oo Mar 27 '09 at 17:59
  • I learned MIPS assembly first by studying code, you can use gcc to generate similar code, however I do most of my checking through reverse engineering. – sfossen Mar 27 '09 at 18:02
  • My point is that loading/modifying/storing a value in MIPS is multiple steps, and because it's a limited number of steps, it won't be as easy to spot a race condition, since you're less likely to hit it. That means you can still hit it though. – sfossen Mar 27 '09 at 18:12
  • Interesting and alarming reminder about storing 32 bit constant requiring in general two instructions in RISC architecture. It seems the storing of the value to memory could be made atomic by constructing the value into a register and storing its value to memory - this would add one extra instruction. Maybe declaring variable `volatile` would force this extra instruction? – FooF Jun 20 '12 at 04:32
  • 1
    Check your disassembly there ... that is all for loading a value into a **register**. What needs to be atomic in order to avoid thread A seeing half of a value written by thread B is that the memory fetch / store is a single atomic instruction, which from what I can find, it is for at least 32 bit values on MIPS32. – Cheetah Aug 16 '12 at 22:56
  • @oo_olo_oo most Unix/Linux implementations use LP64 data model in which int is 32 bits on 64-bit platforms – phuclv Jun 15 '14 at 14:03
  • Registers are thread-private in the first place. It doesn't matter how many instructions it takes to materialize a value in a register; what matters is how it's stored *to memory*. `lw` and `sw` are atomic, but in C++ you still need `std::atomic` to avoid stuff like having the compiler keep the value in a register instead of storing it. (https://lwn.net/Articles/793253/), or even invent stores or invent loads. (You can use `std::memory_order_relaxed` if you don't need ordering wrt. visibility of other non-atomic operations.) – Peter Cordes Mar 12 '22 at 19:18
4

Which operations? It's plausible that int a; a=42; is atomic. There's no guarantee that a= a+42; is atomic, or in any variants like with ++. Also, you have to be concerned about what the optimizer might do, say by holding an intermediate value in a register when convenient.

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • (Also it is plausible that `a=0xdead0b0e` is not atomic – see sfossen's answer above. Here I just want to clarify – because this answer has so many points – that `a=42` is likely atomic because it probably is executed in one assembly instruction but if the constant is larger then the case is different.) – FooF Jun 20 '12 at 04:54
3

The question invites misleading answers.

You can only authoritatively answer "is it atomic" questions about assembly/machine language.

Any given C/C++ code fragment makes no guarantees, can vary depending on exactly which compiler (and version) you use, etc. (Unless you call some platform-specific intrinsic or whatnot that is guaranteed to compile to a known atomic machine instruction.)

Larry Gritz
  • 13,331
  • 5
  • 42
  • 42
  • I don't think its misleading since he said: "on the mips architecture" and gcc – Gustavo Muenz Mar 27 '09 at 16:53
  • But the question is "which version of GCC, with which level of optimization, compiled against which libraries, using which threading model, with what executable format, ... etc.?" – Max Lybbert Mar 27 '09 at 21:41
  • He doesn't say which MIPS chip, or which version of gcc. But mainly I was commenting that any question "...in C" is barking up the wrong tree with atomics. – Larry Gritz Mar 28 '09 at 00:31