On 10/04/2018 23:34, Paul E. McKenney wrote: > Glad it helps, and I have queued it for the next merge window. Of course, > if a further improvement comes to mind, please do not keep it a secret. ;-)
Yes, there are several changes that could be included: - SV could be added to the prior operation case as well? It should be symmetric - The *_relaxed() case also applies to void RMW - smp_store_mb() is missing - smp_rmb() orders prior reads fully against subsequent RMW because SV applies between the two parts of the RMW; likewise smp_wmb() orders prior RMW fully against subsequent writes I am going submit these changes separately, but before doing that I can show also my rewrite of the cheat sheet. The advantage is that, at least to me, it's clearer (and gets rid of "Self" :)). The disadvantage is that it's much longer---almost twice the lines, even if you discount the splitting out of cumulative/propagating to a separate table (which in turn is because to me it's a different level of black magic). --------------------- Memory operations are listed in this document as follows: R: Read portion of RMW W: Write portion of RMW DR: Dependent read (address dependency) DW: Dependent write (address, data, or control dependency) RMW: Atomic read-modify-write operation SV Other accesses to the same variable Memory access operations order other memory operations against themselves as follows: Prior Operation Subsequent Operation --------------- --------------------- R W RMW SV R W DR DW RMW SV - - --- -- - - -- -- --- -- Store, e.g., WRITE_ONCE() Y Y Load, e.g., READ_ONCE() Y Y Y Y Unsuccessful RMW operation Y Y Y Y *_relaxed() or void RMW operation Y Y Y Y rcu_dereference() Y Y Y Y Successful *_acquire() Y r r r r r Y Successful *_release() w w w Y Y smp_store_mb() Y Y Y Y Y Y Y Y Y Y Successful full non-void RMW Y Y Y Y Y Y Y Y Y Y Key: Y: Memory operation provides ordering r: Cannot move past the read portion of the *_acquire() w: Cannot move past the write portion of the *_release() Memory barriers order prior memory operations against subsequent memory operations. Two operations are ordered if both have non-empty cells in the following table: Prior Operation Subsequent Operation --------------- -------------------- R W RMW R W DR DW RMW - - --- - - -- -- --- smp_rmb() Y r Y Y Y smp_wmb() Y Y Y Y w smp_mb() & synchronize_rcu() Y Y Y Y Y Y Y Y smp_mb__before_atomic() Y Y Y a a a a Y smp_mb__after_atomic() a a Y Y Y Y Y Key: Y: Barrier provides ordering r: Barrier provides ordering against the read portion of RMW w: Barrier provides ordering against the write portion of RMW a: Barrier provides ordering given intervening RMW atomic operation Finally the following describes which operations provide cumulative and propagating fences: Cumulative Propagates ---------- ---------- Store, e.g., WRITE_ONCE() Load, e.g., READ_ONCE() Unsuccessful RMW operation *_relaxed() or void RMW operation rcu_dereference() Successful *_acquire() Successful *_release() Y smp_store_mb() Y Y Successful full non-void RMW Y Y smp_rmb() smp_wmb() smp_mb() & synchronize_rcu() Y Y smp_mb__before_atomic() Y Y smp_mb__after_atomic() Y Y ---------- Perhaps you can see some obvious improvements. Otherwise I'll send patches for the above issues. Thanks, Paolo