1811c3c47SYanteng Si.. include:: ../disclaimer-zh_CN.rst 2811c3c47SYanteng Si 3811c3c47SYanteng Si:Original: Documentation/core-api/refcount-vs-atomic.rst 4*8137a49eSYanteng Si 5*8137a49eSYanteng Si:翻译: 6*8137a49eSYanteng Si 7*8137a49eSYanteng Si 司延腾 Yanteng Si <siyanteng@loongson.cn> 8811c3c47SYanteng Si 9811c3c47SYanteng Si.. _cn_refcount-vs-atomic: 10811c3c47SYanteng Si 11811c3c47SYanteng Si======================================= 12811c3c47SYanteng Si与atomic_t相比,refcount_t的API是这样的 13811c3c47SYanteng Si======================================= 14811c3c47SYanteng Si 15811c3c47SYanteng Si.. contents:: :local: 16811c3c47SYanteng Si 17811c3c47SYanteng Si简介 18811c3c47SYanteng Si==== 19811c3c47SYanteng Si 20811c3c47SYanteng Sirefcount_t API的目标是为实现对象的引用计数器提供一个最小的API。虽然来自 21811c3c47SYanteng Silib/refcount.c的独立于架构的通用实现在下面使用了原子操作,但一些 ``refcount_*()`` 22811c3c47SYanteng Si和 ``atomic_*()`` 函数在内存顺序保证方面有很多不同。本文档概述了这些差异,并 23811c3c47SYanteng Si提供了相应的例子,以帮助开发者根据这些内存顺序保证的变化来验证他们的代码。 24811c3c47SYanteng Si 25811c3c47SYanteng Si本文档中使用的术语尽量遵循tools/memory-model/Documentation/explanation.txt 26811c3c47SYanteng Si中定义的正式LKMM。 27811c3c47SYanteng Si 28811c3c47SYanteng Simemory-barriers.txt和atomic_t.txt提供了更多关于内存顺序的背景,包括通用的 29811c3c47SYanteng Si和针对原子操作的。 30811c3c47SYanteng Si 31811c3c47SYanteng Si内存顺序的相关类型 32811c3c47SYanteng Si================== 33811c3c47SYanteng Si 34811c3c47SYanteng Si.. note:: 下面的部分只涵盖了本文使用的与原子操作和引用计数器有关的一些内存顺 35811c3c47SYanteng Si 序类型。如果想了解更广泛的情况,请查阅memory-barriers.txt文件。 36811c3c47SYanteng Si 37811c3c47SYanteng Si在没有任何内存顺序保证的情况下(即完全无序),atomics和refcounters只提供原 38811c3c47SYanteng Si子性和程序顺序(program order, po)关系(在同一个CPU上)。它保证每个 39811c3c47SYanteng Si``atomic_* ()`` 和 ``refcount_*()`` 操作都是原子性的,指令在单个CPU上按程序 40811c3c47SYanteng Si顺序执行。这是用READ_ONCE()/WRITE_ONCE()和比较并交换原语实现的。 41811c3c47SYanteng Si 42811c3c47SYanteng Si强(完全)内存顺序保证在同一CPU上的所有较早加载和存储的指令(所有程序顺序较早 43811c3c47SYanteng Si[po-earlier]指令)在执行任何程序顺序较后指令(po-later)之前完成。它还保证 44811c3c47SYanteng Si同一CPU上储存的程序优先较早的指令和来自其他CPU传播的指令必须在该CPU执行任何 45811c3c47SYanteng Si程序顺序较后指令之前传播到其他CPU(A-累积属性)。这是用smp_mb()实现的。 46811c3c47SYanteng Si 47811c3c47SYanteng SiRELEASE内存顺序保证了在同一CPU上所有较早加载和存储的指令(所有程序顺序较早 48811c3c47SYanteng Si指令)在此操作前完成。它还保证同一CPU上储存的程序优先较早的指令和来自其他CPU 49811c3c47SYanteng Si传播的指令必须在释放(release)操作之前传播到所有其他CPU(A-累积属性)。这是用 50811c3c47SYanteng Sismp_store_release()实现的。 51811c3c47SYanteng Si 52811c3c47SYanteng SiACQUIRE内存顺序保证了同一CPU上的所有后加载和存储的指令(所有程序顺序较后 53811c3c47SYanteng Si指令)在获取(acquire)操作之后完成。它还保证在获取操作执行后,同一CPU上 54811c3c47SYanteng Si储存的所有程序顺序较后指令必须传播到所有其他CPU。这是用 55811c3c47SYanteng Sismp_acquire__after_ctrl_dep()实现的。 56811c3c47SYanteng Si 57811c3c47SYanteng Si对Refcounters的控制依赖(取决于成功)保证了如果一个对象的引用被成功获得(引用计数 58811c3c47SYanteng Si器的增量或增加行为发生了,函数返回true),那么进一步的存储是针对这个操作的命令。对存 59811c3c47SYanteng Si储的控制依赖没有使用任何明确的屏障来实现,而是依赖于CPU不对存储进行猜测。这只是 60811c3c47SYanteng Si一个单一的CPU关系,对其他CPU不提供任何保证。 61811c3c47SYanteng Si 62811c3c47SYanteng Si 63811c3c47SYanteng Si函数的比较 64811c3c47SYanteng Si========== 65811c3c47SYanteng Si 66811c3c47SYanteng Si情况1) - 非 “读/修改/写”(RMW)操作 67811c3c47SYanteng Si------------------------------------ 68811c3c47SYanteng Si 69811c3c47SYanteng Si函数变化: 70811c3c47SYanteng Si 71811c3c47SYanteng Si * atomic_set() --> refcount_set() 72811c3c47SYanteng Si * atomic_read() --> refcount_read() 73811c3c47SYanteng Si 74811c3c47SYanteng Si内存顺序保证变化: 75811c3c47SYanteng Si 76811c3c47SYanteng Si * none (两者都是完全无序的) 77811c3c47SYanteng Si 78811c3c47SYanteng Si 79811c3c47SYanteng Si情况2) - 基于增量的操作,不返回任何值 80811c3c47SYanteng Si-------------------------------------- 81811c3c47SYanteng Si 82811c3c47SYanteng Si函数变化: 83811c3c47SYanteng Si 84811c3c47SYanteng Si * atomic_inc() --> refcount_inc() 85811c3c47SYanteng Si * atomic_add() --> refcount_add() 86811c3c47SYanteng Si 87811c3c47SYanteng Si内存顺序保证变化: 88811c3c47SYanteng Si 89811c3c47SYanteng Si * none (两者都是完全无序的) 90811c3c47SYanteng Si 91811c3c47SYanteng Si情况3) - 基于递减的RMW操作,没有返回值 92811c3c47SYanteng Si--------------------------------------- 93811c3c47SYanteng Si 94811c3c47SYanteng Si函数变化: 95811c3c47SYanteng Si 96811c3c47SYanteng Si * atomic_dec() --> refcount_dec() 97811c3c47SYanteng Si 98811c3c47SYanteng Si内存顺序保证变化: 99811c3c47SYanteng Si 100811c3c47SYanteng Si * 完全无序的 --> RELEASE顺序 101811c3c47SYanteng Si 102811c3c47SYanteng Si 103811c3c47SYanteng Si情况4) - 基于增量的RMW操作,返回一个值 104811c3c47SYanteng Si--------------------------------------- 105811c3c47SYanteng Si 106811c3c47SYanteng Si函数变化: 107811c3c47SYanteng Si 108811c3c47SYanteng Si * atomic_inc_not_zero() --> refcount_inc_not_zero() 109811c3c47SYanteng Si * 无原子性对应函数 --> refcount_add_not_zero() 110811c3c47SYanteng Si 111811c3c47SYanteng Si内存顺序保证变化: 112811c3c47SYanteng Si 113811c3c47SYanteng Si * 完全有序的 --> 控制依赖于存储的成功 114811c3c47SYanteng Si 115811c3c47SYanteng Si.. note:: 此处 **假设** 了,必要的顺序是作为获得对象指针的结果而提供的。 116811c3c47SYanteng Si 117811c3c47SYanteng Si 118811c3c47SYanteng Si情况 5) - 基于Dec/Sub递减的通用RMW操作,返回一个值 119811c3c47SYanteng Si--------------------------------------------------- 120811c3c47SYanteng Si 121811c3c47SYanteng Si函数变化: 122811c3c47SYanteng Si 123811c3c47SYanteng Si * atomic_dec_and_test() --> refcount_dec_and_test() 124811c3c47SYanteng Si * atomic_sub_and_test() --> refcount_sub_and_test() 125811c3c47SYanteng Si 126811c3c47SYanteng Si内存顺序保证变化: 127811c3c47SYanteng Si 128811c3c47SYanteng Si * 完全有序的 --> RELEASE顺序 + 成功后ACQUIRE顺序 129811c3c47SYanteng Si 130811c3c47SYanteng Si 131811c3c47SYanteng Si情况6)其他基于递减的RMW操作,返回一个值 132811c3c47SYanteng Si---------------------------------------- 133811c3c47SYanteng Si 134811c3c47SYanteng Si函数变化: 135811c3c47SYanteng Si 136811c3c47SYanteng Si * 无原子性对应函数 --> refcount_dec_if_one() 137811c3c47SYanteng Si * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)`` 138811c3c47SYanteng Si 139811c3c47SYanteng Si内存顺序保证变化: 140811c3c47SYanteng Si 141811c3c47SYanteng Si * 完全有序的 --> RELEASE顺序 + 控制依赖 142811c3c47SYanteng Si 143811c3c47SYanteng Si.. note:: atomic_add_unless()只在执行成功时提供完整的顺序。 144811c3c47SYanteng Si 145811c3c47SYanteng Si 146811c3c47SYanteng Si情况7)--基于锁的RMW 147811c3c47SYanteng Si-------------------- 148811c3c47SYanteng Si 149811c3c47SYanteng Si函数变化: 150811c3c47SYanteng Si 151811c3c47SYanteng Si * atomic_dec_and_lock() --> refcount_dec_and_lock() 152811c3c47SYanteng Si * atomic_dec_and_mutex_lock() --> refcount_dec_and_mutex_lock() 153811c3c47SYanteng Si 154811c3c47SYanteng Si内存顺序保证变化: 155811c3c47SYanteng Si 156811c3c47SYanteng Si * 完全有序 --> RELEASE顺序 + 控制依赖 + 持有 157