xref: /OK3568_Linux_fs/kernel/Documentation/core-api/refcount-vs-atomic.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun===================================
2*4882a593Smuzhiyunrefcount_t API compared to atomic_t
3*4882a593Smuzhiyun===================================
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun.. contents:: :local:
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunIntroduction
8*4882a593Smuzhiyun============
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunThe goal of refcount_t API is to provide a minimal API for implementing
11*4882a593Smuzhiyunan object's reference counters. While a generic architecture-independent
12*4882a593Smuzhiyunimplementation from lib/refcount.c uses atomic operations underneath,
13*4882a593Smuzhiyunthere are a number of differences between some of the ``refcount_*()`` and
14*4882a593Smuzhiyun``atomic_*()`` functions with regards to the memory ordering guarantees.
15*4882a593SmuzhiyunThis document outlines the differences and provides respective examples
16*4882a593Smuzhiyunin order to help maintainers validate their code against the change in
17*4882a593Smuzhiyunthese memory ordering guarantees.
18*4882a593Smuzhiyun
19*4882a593SmuzhiyunThe terms used through this document try to follow the formal LKMM defined in
20*4882a593Smuzhiyuntools/memory-model/Documentation/explanation.txt.
21*4882a593Smuzhiyun
22*4882a593Smuzhiyunmemory-barriers.txt and atomic_t.txt provide more background to the
23*4882a593Smuzhiyunmemory ordering in general and for atomic operations specifically.
24*4882a593Smuzhiyun
25*4882a593SmuzhiyunRelevant types of memory ordering
26*4882a593Smuzhiyun=================================
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun.. note:: The following section only covers some of the memory
29*4882a593Smuzhiyun   ordering types that are relevant for the atomics and reference
30*4882a593Smuzhiyun   counters and used through this document. For a much broader picture
31*4882a593Smuzhiyun   please consult memory-barriers.txt document.
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunIn the absence of any memory ordering guarantees (i.e. fully unordered)
34*4882a593Smuzhiyunatomics & refcounters only provide atomicity and
35*4882a593Smuzhiyunprogram order (po) relation (on the same CPU). It guarantees that
36*4882a593Smuzhiyuneach ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
37*4882a593Smuzhiyunare executed in program order on a single CPU.
38*4882a593SmuzhiyunThis is implemented using READ_ONCE()/WRITE_ONCE() and
39*4882a593Smuzhiyuncompare-and-swap primitives.
40*4882a593Smuzhiyun
41*4882a593SmuzhiyunA strong (full) memory ordering guarantees that all prior loads and
42*4882a593Smuzhiyunstores (all po-earlier instructions) on the same CPU are completed
43*4882a593Smuzhiyunbefore any po-later instruction is executed on the same CPU.
44*4882a593SmuzhiyunIt also guarantees that all po-earlier stores on the same CPU
45*4882a593Smuzhiyunand all propagated stores from other CPUs must propagate to all
46*4882a593Smuzhiyunother CPUs before any po-later instruction is executed on the original
47*4882a593SmuzhiyunCPU (A-cumulative property). This is implemented using smp_mb().
48*4882a593Smuzhiyun
49*4882a593SmuzhiyunA RELEASE memory ordering guarantees that all prior loads and
50*4882a593Smuzhiyunstores (all po-earlier instructions) on the same CPU are completed
51*4882a593Smuzhiyunbefore the operation. It also guarantees that all po-earlier
52*4882a593Smuzhiyunstores on the same CPU and all propagated stores from other CPUs
53*4882a593Smuzhiyunmust propagate to all other CPUs before the release operation
54*4882a593Smuzhiyun(A-cumulative property). This is implemented using
55*4882a593Smuzhiyunsmp_store_release().
56*4882a593Smuzhiyun
57*4882a593SmuzhiyunAn ACQUIRE memory ordering guarantees that all post loads and
58*4882a593Smuzhiyunstores (all po-later instructions) on the same CPU are
59*4882a593Smuzhiyuncompleted after the acquire operation. It also guarantees that all
60*4882a593Smuzhiyunpo-later stores on the same CPU must propagate to all other CPUs
61*4882a593Smuzhiyunafter the acquire operation executes. This is implemented using
62*4882a593Smuzhiyunsmp_acquire__after_ctrl_dep().
63*4882a593Smuzhiyun
64*4882a593SmuzhiyunA control dependency (on success) for refcounters guarantees that
65*4882a593Smuzhiyunif a reference for an object was successfully obtained (reference
66*4882a593Smuzhiyuncounter increment or addition happened, function returned true),
67*4882a593Smuzhiyunthen further stores are ordered against this operation.
68*4882a593SmuzhiyunControl dependency on stores are not implemented using any explicit
69*4882a593Smuzhiyunbarriers, but rely on CPU not to speculate on stores. This is only
70*4882a593Smuzhiyuna single CPU relation and provides no guarantees for other CPUs.
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun
73*4882a593SmuzhiyunComparison of functions
74*4882a593Smuzhiyun=======================
75*4882a593Smuzhiyun
76*4882a593Smuzhiyuncase 1) - non-"Read/Modify/Write" (RMW) ops
77*4882a593Smuzhiyun-------------------------------------------
78*4882a593Smuzhiyun
79*4882a593SmuzhiyunFunction changes:
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun * atomic_set() --> refcount_set()
82*4882a593Smuzhiyun * atomic_read() --> refcount_read()
83*4882a593Smuzhiyun
84*4882a593SmuzhiyunMemory ordering guarantee changes:
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun * none (both fully unordered)
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun
89*4882a593Smuzhiyuncase 2) - increment-based ops that return no value
90*4882a593Smuzhiyun--------------------------------------------------
91*4882a593Smuzhiyun
92*4882a593SmuzhiyunFunction changes:
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun * atomic_inc() --> refcount_inc()
95*4882a593Smuzhiyun * atomic_add() --> refcount_add()
96*4882a593Smuzhiyun
97*4882a593SmuzhiyunMemory ordering guarantee changes:
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun * none (both fully unordered)
100*4882a593Smuzhiyun
101*4882a593Smuzhiyuncase 3) - decrement-based RMW ops that return no value
102*4882a593Smuzhiyun------------------------------------------------------
103*4882a593Smuzhiyun
104*4882a593SmuzhiyunFunction changes:
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun * atomic_dec() --> refcount_dec()
107*4882a593Smuzhiyun
108*4882a593SmuzhiyunMemory ordering guarantee changes:
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun * fully unordered --> RELEASE ordering
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun
113*4882a593Smuzhiyuncase 4) - increment-based RMW ops that return a value
114*4882a593Smuzhiyun-----------------------------------------------------
115*4882a593Smuzhiyun
116*4882a593SmuzhiyunFunction changes:
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun * atomic_inc_not_zero() --> refcount_inc_not_zero()
119*4882a593Smuzhiyun * no atomic counterpart --> refcount_add_not_zero()
120*4882a593Smuzhiyun
121*4882a593SmuzhiyunMemory ordering guarantees changes:
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun * fully ordered --> control dependency on success for stores
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun.. note:: We really assume here that necessary ordering is provided as a
126*4882a593Smuzhiyun   result of obtaining pointer to the object!
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun
129*4882a593Smuzhiyuncase 5) - generic dec/sub decrement-based RMW ops that return a value
130*4882a593Smuzhiyun---------------------------------------------------------------------
131*4882a593Smuzhiyun
132*4882a593SmuzhiyunFunction changes:
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun * atomic_dec_and_test() --> refcount_dec_and_test()
135*4882a593Smuzhiyun * atomic_sub_and_test() --> refcount_sub_and_test()
136*4882a593Smuzhiyun
137*4882a593SmuzhiyunMemory ordering guarantees changes:
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun
142*4882a593Smuzhiyuncase 6) other decrement-based RMW ops that return a value
143*4882a593Smuzhiyun---------------------------------------------------------
144*4882a593Smuzhiyun
145*4882a593SmuzhiyunFunction changes:
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun * no atomic counterpart --> refcount_dec_if_one()
148*4882a593Smuzhiyun * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)``
149*4882a593Smuzhiyun
150*4882a593SmuzhiyunMemory ordering guarantees changes:
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun * fully ordered --> RELEASE ordering + control dependency
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun.. note:: atomic_add_unless() only provides full order on success.
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun
157*4882a593Smuzhiyuncase 7) - lock-based RMW
158*4882a593Smuzhiyun------------------------
159*4882a593Smuzhiyun
160*4882a593SmuzhiyunFunction changes:
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun * atomic_dec_and_lock() --> refcount_dec_and_lock()
163*4882a593Smuzhiyun * atomic_dec_and_mutex_lock() --> refcount_dec_and_mutex_lock()
164*4882a593Smuzhiyun
165*4882a593SmuzhiyunMemory ordering guarantees changes:
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun * fully ordered --> RELEASE ordering + control dependency + hold
168*4882a593Smuzhiyun   spin_lock() on success
169