162306a36Sopenharmony_ci===================================
262306a36Sopenharmony_cirefcount_t API compared to atomic_t
362306a36Sopenharmony_ci===================================
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci.. contents:: :local:
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciIntroduction
862306a36Sopenharmony_ci============
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ciThe goal of refcount_t API is to provide a minimal API for implementing
1162306a36Sopenharmony_cian object's reference counters. While a generic architecture-independent
1262306a36Sopenharmony_ciimplementation from lib/refcount.c uses atomic operations underneath,
1362306a36Sopenharmony_cithere are a number of differences between some of the ``refcount_*()`` and
1462306a36Sopenharmony_ci``atomic_*()`` functions with regards to the memory ordering guarantees.
1562306a36Sopenharmony_ciThis document outlines the differences and provides respective examples
1662306a36Sopenharmony_ciin order to help maintainers validate their code against the change in
1762306a36Sopenharmony_cithese memory ordering guarantees.
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciThe terms used through this document try to follow the formal LKMM defined in
2062306a36Sopenharmony_citools/memory-model/Documentation/explanation.txt.
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cimemory-barriers.txt and atomic_t.txt provide more background to the
2362306a36Sopenharmony_cimemory ordering in general and for atomic operations specifically.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciRelevant types of memory ordering
2662306a36Sopenharmony_ci=================================
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci.. note:: The following section only covers some of the memory
2962306a36Sopenharmony_ci   ordering types that are relevant for the atomics and reference
3062306a36Sopenharmony_ci   counters and used through this document. For a much broader picture
3162306a36Sopenharmony_ci   please consult memory-barriers.txt document.
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciIn the absence of any memory ordering guarantees (i.e. fully unordered)
3462306a36Sopenharmony_ciatomics & refcounters only provide atomicity and
3562306a36Sopenharmony_ciprogram order (po) relation (on the same CPU). It guarantees that
3662306a36Sopenharmony_cieach ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
3762306a36Sopenharmony_ciare executed in program order on a single CPU.
3862306a36Sopenharmony_ciThis is implemented using READ_ONCE()/WRITE_ONCE() and
3962306a36Sopenharmony_cicompare-and-swap primitives.
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciA strong (full) memory ordering guarantees that all prior loads and
4262306a36Sopenharmony_cistores (all po-earlier instructions) on the same CPU are completed
4362306a36Sopenharmony_cibefore any po-later instruction is executed on the same CPU.
4462306a36Sopenharmony_ciIt also guarantees that all po-earlier stores on the same CPU
4562306a36Sopenharmony_ciand all propagated stores from other CPUs must propagate to all
4662306a36Sopenharmony_ciother CPUs before any po-later instruction is executed on the original
4762306a36Sopenharmony_ciCPU (A-cumulative property). This is implemented using smp_mb().
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciA RELEASE memory ordering guarantees that all prior loads and
5062306a36Sopenharmony_cistores (all po-earlier instructions) on the same CPU are completed
5162306a36Sopenharmony_cibefore the operation. It also guarantees that all po-earlier
5262306a36Sopenharmony_cistores on the same CPU and all propagated stores from other CPUs
5362306a36Sopenharmony_cimust propagate to all other CPUs before the release operation
5462306a36Sopenharmony_ci(A-cumulative property). This is implemented using
5562306a36Sopenharmony_cismp_store_release().
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciAn ACQUIRE memory ordering guarantees that all post loads and
5862306a36Sopenharmony_cistores (all po-later instructions) on the same CPU are
5962306a36Sopenharmony_cicompleted after the acquire operation. It also guarantees that all
6062306a36Sopenharmony_cipo-later stores on the same CPU must propagate to all other CPUs
6162306a36Sopenharmony_ciafter the acquire operation executes. This is implemented using
6262306a36Sopenharmony_cismp_acquire__after_ctrl_dep().
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciA control dependency (on success) for refcounters guarantees that
6562306a36Sopenharmony_ciif a reference for an object was successfully obtained (reference
6662306a36Sopenharmony_cicounter increment or addition happened, function returned true),
6762306a36Sopenharmony_cithen further stores are ordered against this operation.
6862306a36Sopenharmony_ciControl dependency on stores are not implemented using any explicit
6962306a36Sopenharmony_cibarriers, but rely on CPU not to speculate on stores. This is only
7062306a36Sopenharmony_cia single CPU relation and provides no guarantees for other CPUs.
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciComparison of functions
7462306a36Sopenharmony_ci=======================
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cicase 1) - non-"Read/Modify/Write" (RMW) ops
7762306a36Sopenharmony_ci-------------------------------------------
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ciFunction changes:
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci * atomic_set() --> refcount_set()
8262306a36Sopenharmony_ci * atomic_read() --> refcount_read()
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciMemory ordering guarantee changes:
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci * none (both fully unordered)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cicase 2) - increment-based ops that return no value
9062306a36Sopenharmony_ci--------------------------------------------------
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ciFunction changes:
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci * atomic_inc() --> refcount_inc()
9562306a36Sopenharmony_ci * atomic_add() --> refcount_add()
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciMemory ordering guarantee changes:
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci * none (both fully unordered)
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cicase 3) - decrement-based RMW ops that return no value
10262306a36Sopenharmony_ci------------------------------------------------------
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciFunction changes:
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci * atomic_dec() --> refcount_dec()
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciMemory ordering guarantee changes:
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci * fully unordered --> RELEASE ordering
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cicase 4) - increment-based RMW ops that return a value
11462306a36Sopenharmony_ci-----------------------------------------------------
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciFunction changes:
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci * atomic_inc_not_zero() --> refcount_inc_not_zero()
11962306a36Sopenharmony_ci * no atomic counterpart --> refcount_add_not_zero()
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ciMemory ordering guarantees changes:
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci * fully ordered --> control dependency on success for stores
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci.. note:: We really assume here that necessary ordering is provided as a
12662306a36Sopenharmony_ci   result of obtaining pointer to the object!
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cicase 5) - generic dec/sub decrement-based RMW ops that return a value
13062306a36Sopenharmony_ci---------------------------------------------------------------------
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ciFunction changes:
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci * atomic_dec_and_test() --> refcount_dec_and_test()
13562306a36Sopenharmony_ci * atomic_sub_and_test() --> refcount_sub_and_test()
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ciMemory ordering guarantees changes:
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cicase 6) other decrement-based RMW ops that return a value
14362306a36Sopenharmony_ci---------------------------------------------------------
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ciFunction changes:
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci * no atomic counterpart --> refcount_dec_if_one()
14862306a36Sopenharmony_ci * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)``
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ciMemory ordering guarantees changes:
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci * fully ordered --> RELEASE ordering + control dependency
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci.. note:: atomic_add_unless() only provides full order on success.
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cicase 7) - lock-based RMW
15862306a36Sopenharmony_ci------------------------
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ciFunction changes:
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci * atomic_dec_and_lock() --> refcount_dec_and_lock()
16362306a36Sopenharmony_ci * atomic_dec_and_mutex_lock() --> refcount_dec_and_mutex_lock()
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ciMemory ordering guarantees changes:
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci * fully ordered --> RELEASE ordering + control dependency + hold
16862306a36Sopenharmony_ci   spin_lock() on success
169