0001 ===================================
0002 refcount_t API compared to atomic_t
0003 ===================================
0004
0005 .. contents:: :local:
0006
0007 Introduction
0008 ============
0009
0010 The goal of refcount_t API is to provide a minimal API for implementing
0011 an object's reference counters. While a generic architecture-independent
0012 implementation from lib/refcount.c uses atomic operations underneath,
0013 there are a number of differences between some of the ``refcount_*()`` and
0014 ``atomic_*()`` functions with regards to the memory ordering guarantees.
0015 This document outlines the differences and provides respective examples
0016 in order to help maintainers validate their code against the change in
0017 these memory ordering guarantees.
0018
0019 The terms used through this document try to follow the formal LKMM defined in
0020 tools/memory-model/Documentation/explanation.txt.
0021
0022 memory-barriers.txt and atomic_t.txt provide more background to the
0023 memory ordering in general and for atomic operations specifically.
0024
0025 Relevant types of memory ordering
0026 =================================
0027
0028 .. note:: The following section only covers some of the memory
0029 ordering types that are relevant for the atomics and reference
0030 counters and used through this document. For a much broader picture
0031 please consult memory-barriers.txt document.
0032
0033 In the absence of any memory ordering guarantees (i.e. fully unordered)
0034 atomics & refcounters only provide atomicity and
0035 program order (po) relation (on the same CPU). It guarantees that
0036 each ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
0037 are executed in program order on a single CPU.
0038 This is implemented using READ_ONCE()/WRITE_ONCE() and
0039 compare-and-swap primitives.
0040
0041 A strong (full) memory ordering guarantees that all prior loads and
0042 stores (all po-earlier instructions) on the same CPU are completed
0043 before any po-later instruction is executed on the same CPU.
0044 It also guarantees that all po-earlier stores on the same CPU
0045 and all propagated stores from other CPUs must propagate to all
0046 other CPUs before any po-later instruction is executed on the original
0047 CPU (A-cumulative property). This is implemented using smp_mb().
0048
0049 A RELEASE memory ordering guarantees that all prior loads and
0050 stores (all po-earlier instructions) on the same CPU are completed
0051 before the operation. It also guarantees that all po-earlier
0052 stores on the same CPU and all propagated stores from other CPUs
0053 must propagate to all other CPUs before the release operation
0054 (A-cumulative property). This is implemented using
0055 smp_store_release().
0056
0057 An ACQUIRE memory ordering guarantees that all post loads and
0058 stores (all po-later instructions) on the same CPU are
0059 completed after the acquire operation. It also guarantees that all
0060 po-later stores on the same CPU must propagate to all other CPUs
0061 after the acquire operation executes. This is implemented using
0062 smp_acquire__after_ctrl_dep().
0063
0064 A control dependency (on success) for refcounters guarantees that
0065 if a reference for an object was successfully obtained (reference
0066 counter increment or addition happened, function returned true),
0067 then further stores are ordered against this operation.
0068 Control dependency on stores are not implemented using any explicit
0069 barriers, but rely on CPU not to speculate on stores. This is only
0070 a single CPU relation and provides no guarantees for other CPUs.
0071
0072
0073 Comparison of functions
0074 =======================
0075
0076 case 1) - non-"Read/Modify/Write" (RMW) ops
0077 -------------------------------------------
0078
0079 Function changes:
0080
0081 * atomic_set() --> refcount_set()
0082 * atomic_read() --> refcount_read()
0083
0084 Memory ordering guarantee changes:
0085
0086 * none (both fully unordered)
0087
0088
0089 case 2) - increment-based ops that return no value
0090 --------------------------------------------------
0091
0092 Function changes:
0093
0094 * atomic_inc() --> refcount_inc()
0095 * atomic_add() --> refcount_add()
0096
0097 Memory ordering guarantee changes:
0098
0099 * none (both fully unordered)
0100
0101 case 3) - decrement-based RMW ops that return no value
0102 ------------------------------------------------------
0103
0104 Function changes:
0105
0106 * atomic_dec() --> refcount_dec()
0107
0108 Memory ordering guarantee changes:
0109
0110 * fully unordered --> RELEASE ordering
0111
0112
0113 case 4) - increment-based RMW ops that return a value
0114 -----------------------------------------------------
0115
0116 Function changes:
0117
0118 * atomic_inc_not_zero() --> refcount_inc_not_zero()
0119 * no atomic counterpart --> refcount_add_not_zero()
0120
0121 Memory ordering guarantees changes:
0122
0123 * fully ordered --> control dependency on success for stores
0124
0125 .. note:: We really assume here that necessary ordering is provided as a
0126 result of obtaining pointer to the object!
0127
0128
0129 case 5) - generic dec/sub decrement-based RMW ops that return a value
0130 ---------------------------------------------------------------------
0131
0132 Function changes:
0133
0134 * atomic_dec_and_test() --> refcount_dec_and_test()
0135 * atomic_sub_and_test() --> refcount_sub_and_test()
0136
0137 Memory ordering guarantees changes:
0138
0139 * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
0140
0141
0142 case 6) other decrement-based RMW ops that return a value
0143 ---------------------------------------------------------
0144
0145 Function changes:
0146
0147 * no atomic counterpart --> refcount_dec_if_one()
0148 * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)``
0149
0150 Memory ordering guarantees changes:
0151
0152 * fully ordered --> RELEASE ordering + control dependency
0153
0154 .. note:: atomic_add_unless() only provides full order on success.
0155
0156
0157 case 7) - lock-based RMW
0158 ------------------------
0159
0160 Function changes:
0161
0162 * atomic_dec_and_lock() --> refcount_dec_and_lock()
0163 * atomic_dec_and_mutex_lock() --> refcount_dec_and_mutex_lock()
0164
0165 Memory ordering guarantees changes:
0166
0167 * fully ordered --> RELEASE ordering + control dependency + hold
0168 spin_lock() on success