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

Reply via email to