Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

docs: refcount_t documentation

Some functions from refcount_t API provide different
memory ordering guarantees that their atomic counterparts.
This adds a document outlining these differences (
Documentation/core-api/refcount-vs-atomic.rst) as well as
some other minor improvements.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>

authored by

Elena Reshetova and committed by
Jonathan Corbet
b6e859f6 3ece7805

+167 -7
+1
Documentation/core-api/index.rst
··· 14 14 kernel-api 15 15 assoc_array 16 16 atomic_ops 17 + refcount-vs-atomic 17 18 cpu_hotplug 18 19 local_ops 19 20 workqueue
+150
Documentation/core-api/refcount-vs-atomic.rst
··· 1 + =================================== 2 + refcount_t API compared to atomic_t 3 + =================================== 4 + 5 + .. contents:: :local: 6 + 7 + Introduction 8 + ============ 9 + 10 + The goal of refcount_t API is to provide a minimal API for implementing 11 + an object's reference counters. While a generic architecture-independent 12 + implementation from lib/refcount.c uses atomic operations underneath, 13 + there are a number of differences between some of the ``refcount_*()`` and 14 + ``atomic_*()`` functions with regards to the memory ordering guarantees. 15 + This document outlines the differences and provides respective examples 16 + in order to help maintainers validate their code against the change in 17 + these memory ordering guarantees. 18 + 19 + The terms used through this document try to follow the formal LKMM defined in 20 + github.com/aparri/memory-model/blob/master/Documentation/explanation.txt 21 + 22 + memory-barriers.txt and atomic_t.txt provide more background to the 23 + memory ordering in general and for atomic operations specifically. 24 + 25 + Relevant types of memory ordering 26 + ================================= 27 + 28 + .. note:: The following section only covers some of the memory 29 + ordering types that are relevant for the atomics and reference 30 + counters and used through this document. For a much broader picture 31 + please consult memory-barriers.txt document. 32 + 33 + In the absence of any memory ordering guarantees (i.e. fully unordered) 34 + atomics & refcounters only provide atomicity and 35 + program order (po) relation (on the same CPU). It guarantees that 36 + each ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions 37 + are executed in program order on a single CPU. 38 + This is implemented using :c:func:`READ_ONCE`/:c:func:`WRITE_ONCE` and 39 + compare-and-swap primitives. 40 + 41 + A strong (full) memory ordering guarantees that all prior loads and 42 + stores (all po-earlier instructions) on the same CPU are completed 43 + before any po-later instruction is executed on the same CPU. 44 + It also guarantees that all po-earlier stores on the same CPU 45 + and all propagated stores from other CPUs must propagate to all 46 + other CPUs before any po-later instruction is executed on the original 47 + CPU (A-cumulative property). This is implemented using :c:func:`smp_mb`. 48 + 49 + A RELEASE memory ordering guarantees that all prior loads and 50 + stores (all po-earlier instructions) on the same CPU are completed 51 + before the operation. It also guarantees that all po-earlier 52 + stores on the same CPU and all propagated stores from other CPUs 53 + must propagate to all other CPUs before the release operation 54 + (A-cumulative property). This is implemented using 55 + :c:func:`smp_store_release`. 56 + 57 + A control dependency (on success) for refcounters guarantees that 58 + if a reference for an object was successfully obtained (reference 59 + counter increment or addition happened, function returned true), 60 + then further stores are ordered against this operation. 61 + Control dependency on stores are not implemented using any explicit 62 + barriers, but rely on CPU not to speculate on stores. This is only 63 + a single CPU relation and provides no guarantees for other CPUs. 64 + 65 + 66 + Comparison of functions 67 + ======================= 68 + 69 + case 1) - non-"Read/Modify/Write" (RMW) ops 70 + ------------------------------------------- 71 + 72 + Function changes: 73 + 74 + * :c:func:`atomic_set` --> :c:func:`refcount_set` 75 + * :c:func:`atomic_read` --> :c:func:`refcount_read` 76 + 77 + Memory ordering guarantee changes: 78 + 79 + * none (both fully unordered) 80 + 81 + 82 + case 2) - increment-based ops that return no value 83 + -------------------------------------------------- 84 + 85 + Function changes: 86 + 87 + * :c:func:`atomic_inc` --> :c:func:`refcount_inc` 88 + * :c:func:`atomic_add` --> :c:func:`refcount_add` 89 + 90 + Memory ordering guarantee changes: 91 + 92 + * none (both fully unordered) 93 + 94 + case 3) - decrement-based RMW ops that return no value 95 + ------------------------------------------------------ 96 + 97 + Function changes: 98 + 99 + * :c:func:`atomic_dec` --> :c:func:`refcount_dec` 100 + 101 + Memory ordering guarantee changes: 102 + 103 + * fully unordered --> RELEASE ordering 104 + 105 + 106 + case 4) - increment-based RMW ops that return a value 107 + ----------------------------------------------------- 108 + 109 + Function changes: 110 + 111 + * :c:func:`atomic_inc_not_zero` --> :c:func:`refcount_inc_not_zero` 112 + * no atomic counterpart --> :c:func:`refcount_add_not_zero` 113 + 114 + Memory ordering guarantees changes: 115 + 116 + * fully ordered --> control dependency on success for stores 117 + 118 + .. note:: We really assume here that necessary ordering is provided as a 119 + result of obtaining pointer to the object! 120 + 121 + 122 + case 5) - decrement-based RMW ops that return a value 123 + ----------------------------------------------------- 124 + 125 + Function changes: 126 + 127 + * :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test` 128 + * :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test` 129 + * no atomic counterpart --> :c:func:`refcount_dec_if_one` 130 + * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)`` 131 + 132 + Memory ordering guarantees changes: 133 + 134 + * fully ordered --> RELEASE ordering + control dependency 135 + 136 + .. note:: :c:func:`atomic_add_unless` only provides full order on success. 137 + 138 + 139 + case 6) - lock-based RMW 140 + ------------------------ 141 + 142 + Function changes: 143 + 144 + * :c:func:`atomic_dec_and_lock` --> :c:func:`refcount_dec_and_lock` 145 + * :c:func:`atomic_dec_and_mutex_lock` --> :c:func:`refcount_dec_and_mutex_lock` 146 + 147 + Memory ordering guarantees changes: 148 + 149 + * fully ordered --> RELEASE ordering + control dependency + hold 150 + :c:func:`spin_lock` on success
+15 -6
Documentation/driver-api/basics.rst
··· 13 13 .. kernel-doc:: include/linux/mod_devicetable.h 14 14 :internal: 15 15 16 - Atomic and pointer manipulation 17 - ------------------------------- 18 - 19 - .. kernel-doc:: arch/x86/include/asm/atomic.h 20 - :internal: 21 - 22 16 Delaying, scheduling, and timer routines 23 17 ---------------------------------------- 24 18 ··· 78 84 79 85 .. kernel-doc:: kernel/kthread.c 80 86 :export: 87 + 88 + Reference counting 89 + ------------------ 90 + 91 + .. kernel-doc:: include/linux/refcount.h 92 + :internal: 93 + 94 + .. kernel-doc:: lib/refcount.c 95 + :export: 96 + 97 + Atomics 98 + ------- 99 + 100 + .. kernel-doc:: arch/x86/include/asm/atomic.h 101 + :internal: 81 102 82 103 Kernel objects manipulation 83 104 ---------------------------
+1 -1
include/linux/refcount.h
··· 8 8 #include <linux/kernel.h> 9 9 10 10 /** 11 - * refcount_t - variant of atomic_t specialized for reference counts 11 + * struct refcount_t - variant of atomic_t specialized for reference counts 12 12 * @refs: atomic_t counter field 13 13 * 14 14 * The counter saturates at UINT_MAX and will not move once