If I have atomic_bool flag;
, how can I write C code to toggle it that's atomic, portable, and efficient? Regarding "efficient", I'd like it to assemble on x86_64 to lock xorb $1, flag(%rip)
. The "obvious" flag = !flag;
is out because it isn't actually atomic. My next guess would be flag ^= true;
, which assembled to this mess on GCC:
movzbl flag(%rip), %eax
0:
movb %al, -1(%rsp)
xorl $1, %eax
movl %eax, %edx
movzbl -1(%rsp), %eax
lock cmpxchgb %dl, flag(%rip)
jne 0b
And this mess on Clang:
movb flag(%rip), %al
0:
andb $1, %al
movl %eax, %ecx
xorb $1, %cl
lock cmpxchgb %cl, flag(%rip)
jne 0b
Then I tried specifying a weaker memory order by doing atomic_fetch_xor_explicit(&flag, true, memory_order_acq_rel);
instead. This does what I want on Clang, but GCC now completely fails to compile it with error: operand type '_Atomic atomic_bool *' {aka '_Atomic _Bool *'} is incompatible with argument 1 of '__atomic_fetch_xor'
. Interestingly, if my type is an atomic_char
instead of an atomic_bool
, then both GCC and Clang emit the assembly that I want. Is there a way to do what I want with atomic_bool
?