18c2ecf20Sopenharmony_ci===================================
28c2ecf20Sopenharmony_cirefcount_t API compared to atomic_t
38c2ecf20Sopenharmony_ci===================================
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci.. contents:: :local:
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciIntroduction
88c2ecf20Sopenharmony_ci============
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ciThe goal of refcount_t API is to provide a minimal API for implementing
118c2ecf20Sopenharmony_cian object's reference counters. While a generic architecture-independent
128c2ecf20Sopenharmony_ciimplementation from lib/refcount.c uses atomic operations underneath,
138c2ecf20Sopenharmony_cithere are a number of differences between some of the ``refcount_*()`` and
148c2ecf20Sopenharmony_ci``atomic_*()`` functions with regards to the memory ordering guarantees.
158c2ecf20Sopenharmony_ciThis document outlines the differences and provides respective examples
168c2ecf20Sopenharmony_ciin order to help maintainers validate their code against the change in
178c2ecf20Sopenharmony_cithese memory ordering guarantees.
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciThe terms used through this document try to follow the formal LKMM defined in
208c2ecf20Sopenharmony_citools/memory-model/Documentation/explanation.txt.
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cimemory-barriers.txt and atomic_t.txt provide more background to the
238c2ecf20Sopenharmony_cimemory ordering in general and for atomic operations specifically.
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ciRelevant types of memory ordering
268c2ecf20Sopenharmony_ci=================================
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci.. note:: The following section only covers some of the memory
298c2ecf20Sopenharmony_ci   ordering types that are relevant for the atomics and reference
308c2ecf20Sopenharmony_ci   counters and used through this document. For a much broader picture
318c2ecf20Sopenharmony_ci   please consult memory-barriers.txt document.
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciIn the absence of any memory ordering guarantees (i.e. fully unordered)
348c2ecf20Sopenharmony_ciatomics & refcounters only provide atomicity and
358c2ecf20Sopenharmony_ciprogram order (po) relation (on the same CPU). It guarantees that
368c2ecf20Sopenharmony_cieach ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
378c2ecf20Sopenharmony_ciare executed in program order on a single CPU.
388c2ecf20Sopenharmony_ciThis is implemented using READ_ONCE()/WRITE_ONCE() and
398c2ecf20Sopenharmony_cicompare-and-swap primitives.
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ciA strong (full) memory ordering guarantees that all prior loads and
428c2ecf20Sopenharmony_cistores (all po-earlier instructions) on the same CPU are completed
438c2ecf20Sopenharmony_cibefore any po-later instruction is executed on the same CPU.
448c2ecf20Sopenharmony_ciIt also guarantees that all po-earlier stores on the same CPU
458c2ecf20Sopenharmony_ciand all propagated stores from other CPUs must propagate to all
468c2ecf20Sopenharmony_ciother CPUs before any po-later instruction is executed on the original
478c2ecf20Sopenharmony_ciCPU (A-cumulative property). This is implemented using smp_mb().
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ciA RELEASE memory ordering guarantees that all prior loads and
508c2ecf20Sopenharmony_cistores (all po-earlier instructions) on the same CPU are completed
518c2ecf20Sopenharmony_cibefore the operation. It also guarantees that all po-earlier
528c2ecf20Sopenharmony_cistores on the same CPU and all propagated stores from other CPUs
538c2ecf20Sopenharmony_cimust propagate to all other CPUs before the release operation
548c2ecf20Sopenharmony_ci(A-cumulative property). This is implemented using
558c2ecf20Sopenharmony_cismp_store_release().
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ciAn ACQUIRE memory ordering guarantees that all post loads and
588c2ecf20Sopenharmony_cistores (all po-later instructions) on the same CPU are
598c2ecf20Sopenharmony_cicompleted after the acquire operation. It also guarantees that all
608c2ecf20Sopenharmony_cipo-later stores on the same CPU must propagate to all other CPUs
618c2ecf20Sopenharmony_ciafter the acquire operation executes. This is implemented using
628c2ecf20Sopenharmony_cismp_acquire__after_ctrl_dep().
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciA control dependency (on success) for refcounters guarantees that
658c2ecf20Sopenharmony_ciif a reference for an object was successfully obtained (reference
668c2ecf20Sopenharmony_cicounter increment or addition happened, function returned true),
678c2ecf20Sopenharmony_cithen further stores are ordered against this operation.
688c2ecf20Sopenharmony_ciControl dependency on stores are not implemented using any explicit
698c2ecf20Sopenharmony_cibarriers, but rely on CPU not to speculate on stores. This is only
708c2ecf20Sopenharmony_cia single CPU relation and provides no guarantees for other CPUs.
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciComparison of functions
748c2ecf20Sopenharmony_ci=======================
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cicase 1) - non-"Read/Modify/Write" (RMW) ops
778c2ecf20Sopenharmony_ci-------------------------------------------
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ciFunction changes:
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci * atomic_set() --> refcount_set()
828c2ecf20Sopenharmony_ci * atomic_read() --> refcount_read()
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ciMemory ordering guarantee changes:
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci * none (both fully unordered)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cicase 2) - increment-based ops that return no value
908c2ecf20Sopenharmony_ci--------------------------------------------------
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciFunction changes:
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci * atomic_inc() --> refcount_inc()
958c2ecf20Sopenharmony_ci * atomic_add() --> refcount_add()
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciMemory ordering guarantee changes:
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci * none (both fully unordered)
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cicase 3) - decrement-based RMW ops that return no value
1028c2ecf20Sopenharmony_ci------------------------------------------------------
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciFunction changes:
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci * atomic_dec() --> refcount_dec()
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ciMemory ordering guarantee changes:
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci * fully unordered --> RELEASE ordering
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cicase 4) - increment-based RMW ops that return a value
1148c2ecf20Sopenharmony_ci-----------------------------------------------------
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciFunction changes:
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci * atomic_inc_not_zero() --> refcount_inc_not_zero()
1198c2ecf20Sopenharmony_ci * no atomic counterpart --> refcount_add_not_zero()
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciMemory ordering guarantees changes:
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci * fully ordered --> control dependency on success for stores
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci.. note:: We really assume here that necessary ordering is provided as a
1268c2ecf20Sopenharmony_ci   result of obtaining pointer to the object!
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cicase 5) - generic dec/sub decrement-based RMW ops that return a value
1308c2ecf20Sopenharmony_ci---------------------------------------------------------------------
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ciFunction changes:
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci * atomic_dec_and_test() --> refcount_dec_and_test()
1358c2ecf20Sopenharmony_ci * atomic_sub_and_test() --> refcount_sub_and_test()
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ciMemory ordering guarantees changes:
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cicase 6) other decrement-based RMW ops that return a value
1438c2ecf20Sopenharmony_ci---------------------------------------------------------
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ciFunction changes:
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci * no atomic counterpart --> refcount_dec_if_one()
1488c2ecf20Sopenharmony_ci * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)``
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ciMemory ordering guarantees changes:
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci * fully ordered --> RELEASE ordering + control dependency
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci.. note:: atomic_add_unless() only provides full order on success.
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cicase 7) - lock-based RMW
1588c2ecf20Sopenharmony_ci------------------------
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ciFunction changes:
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci * atomic_dec_and_lock() --> refcount_dec_and_lock()
1638c2ecf20Sopenharmony_ci * atomic_dec_and_mutex_lock() --> refcount_dec_and_mutex_lock()
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciMemory ordering guarantees changes:
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci * fully ordered --> RELEASE ordering + control dependency + hold
1688c2ecf20Sopenharmony_ci   spin_lock() on success
169