162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// An earlier version of this file appeared in the companion webpage for 462306a36Sopenharmony_ci// "Frightening small children and disconcerting grown-ups: Concurrency 562306a36Sopenharmony_ci// in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern, 662306a36Sopenharmony_ci// which appeared in ASPLOS 2018. 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci// ONCE 962306a36Sopenharmony_ciREAD_ONCE(X) __load{once}(X) 1062306a36Sopenharmony_ciWRITE_ONCE(X,V) { __store{once}(X,V); } 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci// Release Acquire and friends 1362306a36Sopenharmony_cismp_store_release(X,V) { __store{release}(*X,V); } 1462306a36Sopenharmony_cismp_load_acquire(X) __load{acquire}(*X) 1562306a36Sopenharmony_circu_assign_pointer(X,V) { __store{release}(X,V); } 1662306a36Sopenharmony_circu_dereference(X) __load{once}(X) 1762306a36Sopenharmony_cismp_store_mb(X,V) { __store{once}(X,V); __fence{mb}; } 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci// Fences 2062306a36Sopenharmony_cismp_mb() { __fence{mb}; } 2162306a36Sopenharmony_cismp_rmb() { __fence{rmb}; } 2262306a36Sopenharmony_cismp_wmb() { __fence{wmb}; } 2362306a36Sopenharmony_cismp_mb__before_atomic() { __fence{before-atomic}; } 2462306a36Sopenharmony_cismp_mb__after_atomic() { __fence{after-atomic}; } 2562306a36Sopenharmony_cismp_mb__after_spinlock() { __fence{after-spinlock}; } 2662306a36Sopenharmony_cismp_mb__after_unlock_lock() { __fence{after-unlock-lock}; } 2762306a36Sopenharmony_cismp_mb__after_srcu_read_unlock() { __fence{after-srcu-read-unlock}; } 2862306a36Sopenharmony_cibarrier() { __fence{barrier}; } 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci// Exchange 3162306a36Sopenharmony_cixchg(X,V) __xchg{mb}(X,V) 3262306a36Sopenharmony_cixchg_relaxed(X,V) __xchg{once}(X,V) 3362306a36Sopenharmony_cixchg_release(X,V) __xchg{release}(X,V) 3462306a36Sopenharmony_cixchg_acquire(X,V) __xchg{acquire}(X,V) 3562306a36Sopenharmony_cicmpxchg(X,V,W) __cmpxchg{mb}(X,V,W) 3662306a36Sopenharmony_cicmpxchg_relaxed(X,V,W) __cmpxchg{once}(X,V,W) 3762306a36Sopenharmony_cicmpxchg_acquire(X,V,W) __cmpxchg{acquire}(X,V,W) 3862306a36Sopenharmony_cicmpxchg_release(X,V,W) __cmpxchg{release}(X,V,W) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci// Spinlocks 4162306a36Sopenharmony_cispin_lock(X) { __lock(X); } 4262306a36Sopenharmony_cispin_unlock(X) { __unlock(X); } 4362306a36Sopenharmony_cispin_trylock(X) __trylock(X) 4462306a36Sopenharmony_cispin_is_locked(X) __islocked(X) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci// RCU 4762306a36Sopenharmony_circu_read_lock() { __fence{rcu-lock}; } 4862306a36Sopenharmony_circu_read_unlock() { __fence{rcu-unlock}; } 4962306a36Sopenharmony_cisynchronize_rcu() { __fence{sync-rcu}; } 5062306a36Sopenharmony_cisynchronize_rcu_expedited() { __fence{sync-rcu}; } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci// SRCU 5362306a36Sopenharmony_cisrcu_read_lock(X) __load{srcu-lock}(*X) 5462306a36Sopenharmony_cisrcu_read_unlock(X,Y) { __store{srcu-unlock}(*X,Y); } 5562306a36Sopenharmony_cisrcu_down_read(X) __load{srcu-lock}(*X) 5662306a36Sopenharmony_cisrcu_up_read(X,Y) { __store{srcu-unlock}(*X,Y); } 5762306a36Sopenharmony_cisynchronize_srcu(X) { __srcu{sync-srcu}(X); } 5862306a36Sopenharmony_cisynchronize_srcu_expedited(X) { __srcu{sync-srcu}(X); } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci// Atomic 6162306a36Sopenharmony_ciatomic_read(X) READ_ONCE(*X) 6262306a36Sopenharmony_ciatomic_set(X,V) { WRITE_ONCE(*X,V); } 6362306a36Sopenharmony_ciatomic_read_acquire(X) smp_load_acquire(X) 6462306a36Sopenharmony_ciatomic_set_release(X,V) { smp_store_release(X,V); } 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciatomic_add(V,X) { __atomic_op(X,+,V); } 6762306a36Sopenharmony_ciatomic_sub(V,X) { __atomic_op(X,-,V); } 6862306a36Sopenharmony_ciatomic_inc(X) { __atomic_op(X,+,1); } 6962306a36Sopenharmony_ciatomic_dec(X) { __atomic_op(X,-,1); } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciatomic_add_return(V,X) __atomic_op_return{mb}(X,+,V) 7262306a36Sopenharmony_ciatomic_add_return_relaxed(V,X) __atomic_op_return{once}(X,+,V) 7362306a36Sopenharmony_ciatomic_add_return_acquire(V,X) __atomic_op_return{acquire}(X,+,V) 7462306a36Sopenharmony_ciatomic_add_return_release(V,X) __atomic_op_return{release}(X,+,V) 7562306a36Sopenharmony_ciatomic_fetch_add(V,X) __atomic_fetch_op{mb}(X,+,V) 7662306a36Sopenharmony_ciatomic_fetch_add_relaxed(V,X) __atomic_fetch_op{once}(X,+,V) 7762306a36Sopenharmony_ciatomic_fetch_add_acquire(V,X) __atomic_fetch_op{acquire}(X,+,V) 7862306a36Sopenharmony_ciatomic_fetch_add_release(V,X) __atomic_fetch_op{release}(X,+,V) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciatomic_inc_return(X) __atomic_op_return{mb}(X,+,1) 8162306a36Sopenharmony_ciatomic_inc_return_relaxed(X) __atomic_op_return{once}(X,+,1) 8262306a36Sopenharmony_ciatomic_inc_return_acquire(X) __atomic_op_return{acquire}(X,+,1) 8362306a36Sopenharmony_ciatomic_inc_return_release(X) __atomic_op_return{release}(X,+,1) 8462306a36Sopenharmony_ciatomic_fetch_inc(X) __atomic_fetch_op{mb}(X,+,1) 8562306a36Sopenharmony_ciatomic_fetch_inc_relaxed(X) __atomic_fetch_op{once}(X,+,1) 8662306a36Sopenharmony_ciatomic_fetch_inc_acquire(X) __atomic_fetch_op{acquire}(X,+,1) 8762306a36Sopenharmony_ciatomic_fetch_inc_release(X) __atomic_fetch_op{release}(X,+,1) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ciatomic_sub_return(V,X) __atomic_op_return{mb}(X,-,V) 9062306a36Sopenharmony_ciatomic_sub_return_relaxed(V,X) __atomic_op_return{once}(X,-,V) 9162306a36Sopenharmony_ciatomic_sub_return_acquire(V,X) __atomic_op_return{acquire}(X,-,V) 9262306a36Sopenharmony_ciatomic_sub_return_release(V,X) __atomic_op_return{release}(X,-,V) 9362306a36Sopenharmony_ciatomic_fetch_sub(V,X) __atomic_fetch_op{mb}(X,-,V) 9462306a36Sopenharmony_ciatomic_fetch_sub_relaxed(V,X) __atomic_fetch_op{once}(X,-,V) 9562306a36Sopenharmony_ciatomic_fetch_sub_acquire(V,X) __atomic_fetch_op{acquire}(X,-,V) 9662306a36Sopenharmony_ciatomic_fetch_sub_release(V,X) __atomic_fetch_op{release}(X,-,V) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciatomic_dec_return(X) __atomic_op_return{mb}(X,-,1) 9962306a36Sopenharmony_ciatomic_dec_return_relaxed(X) __atomic_op_return{once}(X,-,1) 10062306a36Sopenharmony_ciatomic_dec_return_acquire(X) __atomic_op_return{acquire}(X,-,1) 10162306a36Sopenharmony_ciatomic_dec_return_release(X) __atomic_op_return{release}(X,-,1) 10262306a36Sopenharmony_ciatomic_fetch_dec(X) __atomic_fetch_op{mb}(X,-,1) 10362306a36Sopenharmony_ciatomic_fetch_dec_relaxed(X) __atomic_fetch_op{once}(X,-,1) 10462306a36Sopenharmony_ciatomic_fetch_dec_acquire(X) __atomic_fetch_op{acquire}(X,-,1) 10562306a36Sopenharmony_ciatomic_fetch_dec_release(X) __atomic_fetch_op{release}(X,-,1) 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciatomic_xchg(X,V) __xchg{mb}(X,V) 10862306a36Sopenharmony_ciatomic_xchg_relaxed(X,V) __xchg{once}(X,V) 10962306a36Sopenharmony_ciatomic_xchg_release(X,V) __xchg{release}(X,V) 11062306a36Sopenharmony_ciatomic_xchg_acquire(X,V) __xchg{acquire}(X,V) 11162306a36Sopenharmony_ciatomic_cmpxchg(X,V,W) __cmpxchg{mb}(X,V,W) 11262306a36Sopenharmony_ciatomic_cmpxchg_relaxed(X,V,W) __cmpxchg{once}(X,V,W) 11362306a36Sopenharmony_ciatomic_cmpxchg_acquire(X,V,W) __cmpxchg{acquire}(X,V,W) 11462306a36Sopenharmony_ciatomic_cmpxchg_release(X,V,W) __cmpxchg{release}(X,V,W) 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciatomic_sub_and_test(V,X) __atomic_op_return{mb}(X,-,V) == 0 11762306a36Sopenharmony_ciatomic_dec_and_test(X) __atomic_op_return{mb}(X,-,1) == 0 11862306a36Sopenharmony_ciatomic_inc_and_test(X) __atomic_op_return{mb}(X,+,1) == 0 11962306a36Sopenharmony_ciatomic_add_negative(V,X) __atomic_op_return{mb}(X,+,V) < 0 120