Suppose I have
aligned uint8_t vars[2] = {0x00, 0x00};
Thread 1:
CAS((uint16_t *)vars, 0x0000, 0x0001);
Thread 2:
store(&vars[0], 0x01);
x = load(&vars[1]);
Assume big endian. Is the outcome [CAS succeeds, x = 0] possible?
[fixed example]
Conversation
Replying to
Accessing uint8_t as uint16_t is undefined. You could define it as uint16_t and access it as char though. However, there's no proper memory model / semantics for old style atomics. You need to use C++11 atomics and they don't support what you want to do in any well defined way.
2
1
3
You could define it as std::atomic_uint16_t but then I don't think it's well-defined to store / load into that as a char pointer. Even if it was, I don't think it fits into their memory model. There's definitely no way to mix different sizes of atomic operations for u8 and u16.
1
Replying to
Yeah, that’s pretty much what I thought. Any idea if I’m right that this will work on real hardware? (Assume I just use inline assembly for the loads/stores to skirt questions about UB.)
1
Replying to
There's an example of it here in the optimized implementation and someone brings up a quote from the Intel manual they think prohibits it: locklessinc.com/articles/mutex.
2
Mixing different sizes of accesses definitely works in practice on real hardware. I've done it before and I've seen production code using it including core x86 Linux kernel code. I'm unsure if it's well-defined at the architectural level and C11/C++11 definitely don't allow it.

