jfbastien wrote:
> > Otherwise an object with dirty padding can make the loop fail forever
>
> Indeed, oh my. Reworking this a little bit, the current design is flawed
>
> This one will indeed loop forever:
>
> ```c++
> #include <stdatomic.h>
> union U {
> _Atomic(_BitInt(37)) a;
> unsigned long b;
> };
>
> int main(void) {
> union U u;
> u.b = ((unsigned long)1 << 40) | 5u; // dirty padding bit + value 5
> (void)__c11_atomic_fetch_add(&u.a, (_BitInt(37))1, memory_order_seq_cst);
> return 0;
> }
> ```
So I think this example, we can decide it always fails. What's the protocol? Do
we mask padding bits after a load, or do we mask them when there's a store? The
former is problematic because then native cmpxchg can't be used (unless we had
hardware that did masking), we need to do load-linked / store-conditional type
loops (with a mask). So IMO, on most platforms, it makes sense to mandate that
store of a padded bitint also masks the non-representation bits. I'm
effectively describing an ABI (hence my concern with GCC).
So if you go with mask at store time, your example would be expected to fail,
always. A better test would then be to store to `b`, then to `a`, and then to
do atomic operations. The store to `a` would have cleared the padding. Your
example would just always fail as it is right now.
Maybe I'm not fully understanding this though! LMK if I've got it wrong.
https://github.com/llvm/llvm-project/pull/204815
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits