mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-28 18:10:32 +00:00

Not all annotated accesses provide the semantics their syntactic tags would imply. For example, an 'acquire tag on a write does not imply that the write is finally in the Acquire set and provides acquire ordering. To distinguish in those cases between the syntactic tags and actual sets, we capitalize the former, so 'ACQUIRE tags may be present on both reads and writes, but only reads will appear in the Acquire set. For tags where the two concepts are the same we do not use specific capitalization to make this distinction. Reported-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Jonas Oberhauser <jonas.oberhauser@huaweicloud.com> Reviewed-by: Boqun Feng <boqun.feng@gmail.com> Tested-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Tested-by: Akira Yokosawa <akiyks@gmail.com> # herdtools7.7.58
149 lines
6.2 KiB
Modula-2
149 lines
6.2 KiB
Modula-2
// SPDX-License-Identifier: GPL-2.0+
|
|
//
|
|
// An earlier version of this file appeared in the companion webpage for
|
|
// "Frightening small children and disconcerting grown-ups: Concurrency
|
|
// in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
|
|
// which appeared in ASPLOS 2018.
|
|
|
|
// ONCE
|
|
READ_ONCE(X) __load{ONCE}(X)
|
|
WRITE_ONCE(X,V) { __store{ONCE}(X,V); }
|
|
|
|
// Release Acquire and friends
|
|
smp_store_release(X,V) { __store{RELEASE}(*X,V); }
|
|
smp_load_acquire(X) __load{ACQUIRE}(*X)
|
|
rcu_assign_pointer(X,V) { __store{RELEASE}(X,V); }
|
|
rcu_dereference(X) __load{ONCE}(X)
|
|
smp_store_mb(X,V) { __store{ONCE}(X,V); __fence{MB}; }
|
|
|
|
// Fences
|
|
smp_mb() { __fence{MB}; }
|
|
smp_rmb() { __fence{rmb}; }
|
|
smp_wmb() { __fence{wmb}; }
|
|
smp_mb__before_atomic() { __fence{before-atomic}; }
|
|
smp_mb__after_atomic() { __fence{after-atomic}; }
|
|
smp_mb__after_spinlock() { __fence{after-spinlock}; }
|
|
smp_mb__after_unlock_lock() { __fence{after-unlock-lock}; }
|
|
smp_mb__after_srcu_read_unlock() { __fence{after-srcu-read-unlock}; }
|
|
barrier() { __fence{barrier}; }
|
|
|
|
// Exchange
|
|
xchg(X,V) __xchg{MB}(X,V)
|
|
xchg_relaxed(X,V) __xchg{ONCE}(X,V)
|
|
xchg_release(X,V) __xchg{RELEASE}(X,V)
|
|
xchg_acquire(X,V) __xchg{ACQUIRE}(X,V)
|
|
cmpxchg(X,V,W) __cmpxchg{MB}(X,V,W)
|
|
cmpxchg_relaxed(X,V,W) __cmpxchg{ONCE}(X,V,W)
|
|
cmpxchg_acquire(X,V,W) __cmpxchg{ACQUIRE}(X,V,W)
|
|
cmpxchg_release(X,V,W) __cmpxchg{RELEASE}(X,V,W)
|
|
|
|
// Spinlocks
|
|
spin_lock(X) { __lock(X); }
|
|
spin_unlock(X) { __unlock(X); }
|
|
spin_trylock(X) __trylock(X)
|
|
spin_is_locked(X) __islocked(X)
|
|
|
|
// RCU
|
|
rcu_read_lock() { __fence{rcu-lock}; }
|
|
rcu_read_unlock() { __fence{rcu-unlock}; }
|
|
synchronize_rcu() { __fence{sync-rcu}; }
|
|
synchronize_rcu_expedited() { __fence{sync-rcu}; }
|
|
|
|
// SRCU
|
|
srcu_read_lock(X) __load{srcu-lock}(*X)
|
|
srcu_read_unlock(X,Y) { __store{srcu-unlock}(*X,Y); }
|
|
srcu_down_read(X) __load{srcu-lock}(*X)
|
|
srcu_up_read(X,Y) { __store{srcu-unlock}(*X,Y); }
|
|
synchronize_srcu(X) { __srcu{sync-srcu}(X); }
|
|
synchronize_srcu_expedited(X) { __srcu{sync-srcu}(X); }
|
|
|
|
// Atomic
|
|
atomic_read(X) READ_ONCE(*X)
|
|
atomic_set(X,V) { WRITE_ONCE(*X,V); }
|
|
atomic_read_acquire(X) smp_load_acquire(X)
|
|
atomic_set_release(X,V) { smp_store_release(X,V); }
|
|
|
|
atomic_add(V,X) { __atomic_op{NORETURN}(X,+,V); }
|
|
atomic_sub(V,X) { __atomic_op{NORETURN}(X,-,V); }
|
|
atomic_and(V,X) { __atomic_op{NORETURN}(X,&,V); }
|
|
atomic_or(V,X) { __atomic_op{NORETURN}(X,|,V); }
|
|
atomic_xor(V,X) { __atomic_op{NORETURN}(X,^,V); }
|
|
atomic_inc(X) { __atomic_op{NORETURN}(X,+,1); }
|
|
atomic_dec(X) { __atomic_op{NORETURN}(X,-,1); }
|
|
atomic_andnot(V,X) { __atomic_op{NORETURN}(X,&~,V); }
|
|
|
|
atomic_add_return(V,X) __atomic_op_return{MB}(X,+,V)
|
|
atomic_add_return_relaxed(V,X) __atomic_op_return{ONCE}(X,+,V)
|
|
atomic_add_return_acquire(V,X) __atomic_op_return{ACQUIRE}(X,+,V)
|
|
atomic_add_return_release(V,X) __atomic_op_return{RELEASE}(X,+,V)
|
|
atomic_fetch_add(V,X) __atomic_fetch_op{MB}(X,+,V)
|
|
atomic_fetch_add_relaxed(V,X) __atomic_fetch_op{ONCE}(X,+,V)
|
|
atomic_fetch_add_acquire(V,X) __atomic_fetch_op{ACQUIRE}(X,+,V)
|
|
atomic_fetch_add_release(V,X) __atomic_fetch_op{RELEASE}(X,+,V)
|
|
|
|
atomic_fetch_and(V,X) __atomic_fetch_op{MB}(X,&,V)
|
|
atomic_fetch_and_relaxed(V,X) __atomic_fetch_op{ONCE}(X,&,V)
|
|
atomic_fetch_and_acquire(V,X) __atomic_fetch_op{ACQUIRE}(X,&,V)
|
|
atomic_fetch_and_release(V,X) __atomic_fetch_op{RELEASE}(X,&,V)
|
|
|
|
atomic_fetch_or(V,X) __atomic_fetch_op{MB}(X,|,V)
|
|
atomic_fetch_or_relaxed(V,X) __atomic_fetch_op{ONCE}(X,|,V)
|
|
atomic_fetch_or_acquire(V,X) __atomic_fetch_op{ACQUIRE}(X,|,V)
|
|
atomic_fetch_or_release(V,X) __atomic_fetch_op{RELEASE}(X,|,V)
|
|
|
|
atomic_fetch_xor(V,X) __atomic_fetch_op{MB}(X,^,V)
|
|
atomic_fetch_xor_relaxed(V,X) __atomic_fetch_op{ONCE}(X,^,V)
|
|
atomic_fetch_xor_acquire(V,X) __atomic_fetch_op{ACQUIRE}(X,^,V)
|
|
atomic_fetch_xor_release(V,X) __atomic_fetch_op{RELEASE}(X,^,V)
|
|
|
|
atomic_inc_return(X) __atomic_op_return{MB}(X,+,1)
|
|
atomic_inc_return_relaxed(X) __atomic_op_return{ONCE}(X,+,1)
|
|
atomic_inc_return_acquire(X) __atomic_op_return{ACQUIRE}(X,+,1)
|
|
atomic_inc_return_release(X) __atomic_op_return{RELEASE}(X,+,1)
|
|
atomic_fetch_inc(X) __atomic_fetch_op{MB}(X,+,1)
|
|
atomic_fetch_inc_relaxed(X) __atomic_fetch_op{ONCE}(X,+,1)
|
|
atomic_fetch_inc_acquire(X) __atomic_fetch_op{ACQUIRE}(X,+,1)
|
|
atomic_fetch_inc_release(X) __atomic_fetch_op{RELEASE}(X,+,1)
|
|
|
|
atomic_sub_return(V,X) __atomic_op_return{MB}(X,-,V)
|
|
atomic_sub_return_relaxed(V,X) __atomic_op_return{ONCE}(X,-,V)
|
|
atomic_sub_return_acquire(V,X) __atomic_op_return{ACQUIRE}(X,-,V)
|
|
atomic_sub_return_release(V,X) __atomic_op_return{RELEASE}(X,-,V)
|
|
atomic_fetch_sub(V,X) __atomic_fetch_op{MB}(X,-,V)
|
|
atomic_fetch_sub_relaxed(V,X) __atomic_fetch_op{ONCE}(X,-,V)
|
|
atomic_fetch_sub_acquire(V,X) __atomic_fetch_op{ACQUIRE}(X,-,V)
|
|
atomic_fetch_sub_release(V,X) __atomic_fetch_op{RELEASE}(X,-,V)
|
|
|
|
atomic_dec_return(X) __atomic_op_return{MB}(X,-,1)
|
|
atomic_dec_return_relaxed(X) __atomic_op_return{ONCE}(X,-,1)
|
|
atomic_dec_return_acquire(X) __atomic_op_return{ACQUIRE}(X,-,1)
|
|
atomic_dec_return_release(X) __atomic_op_return{RELEASE}(X,-,1)
|
|
atomic_fetch_dec(X) __atomic_fetch_op{MB}(X,-,1)
|
|
atomic_fetch_dec_relaxed(X) __atomic_fetch_op{ONCE}(X,-,1)
|
|
atomic_fetch_dec_acquire(X) __atomic_fetch_op{ACQUIRE}(X,-,1)
|
|
atomic_fetch_dec_release(X) __atomic_fetch_op{RELEASE}(X,-,1)
|
|
|
|
atomic_xchg(X,V) __xchg{MB}(X,V)
|
|
atomic_xchg_relaxed(X,V) __xchg{ONCE}(X,V)
|
|
atomic_xchg_release(X,V) __xchg{RELEASE}(X,V)
|
|
atomic_xchg_acquire(X,V) __xchg{ACQUIRE}(X,V)
|
|
atomic_cmpxchg(X,V,W) __cmpxchg{MB}(X,V,W)
|
|
atomic_cmpxchg_relaxed(X,V,W) __cmpxchg{ONCE}(X,V,W)
|
|
atomic_cmpxchg_acquire(X,V,W) __cmpxchg{ACQUIRE}(X,V,W)
|
|
atomic_cmpxchg_release(X,V,W) __cmpxchg{RELEASE}(X,V,W)
|
|
|
|
atomic_sub_and_test(V,X) __atomic_op_return{MB}(X,-,V) == 0
|
|
atomic_dec_and_test(X) __atomic_op_return{MB}(X,-,1) == 0
|
|
atomic_inc_and_test(X) __atomic_op_return{MB}(X,+,1) == 0
|
|
atomic_add_negative(V,X) __atomic_op_return{MB}(X,+,V) < 0
|
|
atomic_add_negative_relaxed(V,X) __atomic_op_return{ONCE}(X,+,V) < 0
|
|
atomic_add_negative_acquire(V,X) __atomic_op_return{ACQUIRE}(X,+,V) < 0
|
|
atomic_add_negative_release(V,X) __atomic_op_return{RELEASE}(X,+,V) < 0
|
|
|
|
atomic_fetch_andnot(V,X) __atomic_fetch_op{MB}(X,&~,V)
|
|
atomic_fetch_andnot_acquire(V,X) __atomic_fetch_op{ACQUIRE}(X,&~,V)
|
|
atomic_fetch_andnot_release(V,X) __atomic_fetch_op{RELEASE}(X,&~,V)
|
|
atomic_fetch_andnot_relaxed(V,X) __atomic_fetch_op{ONCE}(X,&~,V)
|
|
|
|
atomic_add_unless(X,V,W) __atomic_add_unless{MB}(X,V,W)
|