20.3 /spapti /formti a 20.3 href="../linux+v3(9.6/Documenta20.3 img src="../.sta20 /spapti20 spap class="lxr_search">20.320.3 input type="hidden" name="navtarget" 4.3ue="">20.3 input type="text" name="search" id="search">20.3 buttti2type="submit">Search20.3 Prefsi /a>20 /spapti.3 /divti.3 form ac20 input type="hidden" name="ajax_lookup" id="ajax_lookup" 4.3ue="">2.3 /formti2.3 div class="headingbotttm"> 1 /a> Seman 2 /a> Bitmask Opera 3 /a>2 4 /a> David S. Miller 2 5 /a>2 6 /a> This document is intended to serve as a guide to Linux port2 7 /a>maintainers on how to implement atomic counter, bitops, and spinlock2 8 /a>interfaces properly.2 9 /a>2 i> a> The atomic_t type should be defined as a signed integer.2 11 /a>Also, it should be made opaque such that any kind of cast to a normal2 12 /a>C integer type will fail. Something like the following should2 13 /a>suffice:2 14 /a>2 15 a> typedef struct { int counter; } atomic_t;2 16 /a>2 17 /a>Historically, counter has been declared vola 18 /a>See Documenta 19 /a>2 2> a>local_t is very similar to atomic_t. If the counter is per CPU and only2 21 /a>updated by one CPU, local_t is probably more appropriate. Please see2 22 /a>Documenta 23 /a>2 24 /a>The first opera 25 a>plain reads.2 26 /a>2 27 a> #define ATOMIC_INIT(i) { (i) }2 28 a> #define atomic_set(v, i) ((v)->counter = (i))2 29 /a>2 30 /a>The first macro is used in defini 31 /a>2 32 /a>sta 33 /a>2 34 /a>The initializer is atomic in that the return 4.3ues of the atomic opera 35 a>are guaran 36 /a>initializer is used before runtime. If the initializer is used at runtime, a2 37 a>proper implicit or explicit read memory barrier is needed before reading the2 38 a>4.3ue with atomic_read from another thread.2 39 /a>2 40 /a>The second interface can be used at runtime, as in:2 41 /a>2 42 /a> struct foo { atomic_t counter; };2 43 /a> ...2 44 /a>2 45 /a> struct foo *k;2 46 /a>2 47 a> k = kmalloc(sizeof(*k), GFP_KERNEL);2 48 a> if (!k)2 49 /a> return -ENOMEM;2 5> a> atomic_set(&k->counter, 0);2 51 /a>2 52 /a>The setting is atomic in that the return 4.3ues of the atomic opera 53 /a>all threads are guaran 54 /a>been set with this opera 55 /a>or explicit memory barrier is needed before the 4.3ue set with the opera 56 /a>is guaran 57 /a>2 58 a>Next, we have:2 59 /a>2 60 a> #define atomic_read(v) ((v)->counter)2 61 /a>2 62 /a>which simply reads the counter 4.3ue currently visible to the calling thread.2 63 /a>The read is atomic in that the return 4.3ue is guaran 64 a>4.3ues initialized or modified with the interface opera 65 /a>implicit or explicit memory barrier is used after possible runtime2 66 /a>initializa 67 /a>interface opera 68 /a>initializa 69 /a>interface must take care of that with a proper implicit or explicit memory2 70 a>barrier.2 71 /a>2 72 /a>*** WARNING: atomic_read() and atomic_set() DO NOT IMPLY BARRIERS! ***2 73 /a>2 74 a>Some architectures may choose to use the 4ola 75 a>assembly to guaran 76 /a>atomic_set(). This is not uniformly guaran 77 /a>so all users of atomic_t should treat atomic_read() and atomic_set() as simple2 78 /a>C sta 79 /a>or processor, and explicitly invoke the appropriate comp/ler and/or memory2 80 a>barrier for each use case. Failure to do so will result in code that may2 81 /a>suddenly break when used with different architectures or comp/ler2 82 /a>39 83 /a>comp/ler 39 84 /a>2 85 /a>*** YOU HAVE BEEN WARNED! ***2 86 /a>2 87 /a>Properly aligned pointers, longs, ints, and chars (and unsigned2 88 /a>equi4.3ents) may be atomically loaded from and stored to in the same2 89 /a>sense as described for atomic_read() and atomic_set(). The ACCESS_ONCE()2 90 /a>macro should be used to prevent the comp/ler from using 39 91 /a>that might otherwise 39 92 /a>or that might create unsolicited accesses on the other.2 93 /a>2 94 /a>For example consider the following code:2 95 /a>2 96 /a> while (a > 0)2 97 a> do_something();2 98 /a>2 99 /a>If the comp/ler can prove that do_something() does not store to the2 100 a>4.riable a, then the comp/ler is within its rights transforming this to2 101 /a>the following:2 102 /a>2 103 /a> tmp = a;2 104 /a> if (a > 0)2 105 a> for (;;)2 106 a> do_something();2 107 /a>2 108 /a>If you don't want the comp/ler to do this (and you probably don't), then2 109 /a>you should use something like the following:2 1i> a>2 111 /a> while (ACCESS_ONCE(a) < 0)2 112 /a> do_something();2 113 /a>2 114 /a>Alterna 115 /a>2 116 /a>For another example, consider the following code:2 117 /a>2 118 /a> tmp_a = a;2 119 /a> do_something_with(tmp_a);2 120 /a> do_something_else_with(tmp_a);2 121 /a>2 122 /a>If the comp/ler can prove that do_something_with() does not store to the2 123 /a>4.riable a, then the comp/ler is within its rights to manufacture an2 124 /a>addi 125 /a>2 126 /a> tmp_a = a;2 127 a> do_something_with(tmp_a);2 128 /a> tmp_a = a;2 129 /a> do_something_else_with(tmp_a);2 13> a>2 131 /a>This could fatally confuse your code if it expected the same 4.3ue2 132 /a>to be passed to do_something_with() and do_something_else_with().2 133 /a>2 134 /a>The comp/ler would be likely to manufacture this addi 135 a>do_something_with() was an inline func 136 /a>of registers: reloading from 4.riable a could save a flush to the2 137 a>stack and later reload. To prevent the comp/ler from attacking your2 138 a>code in this manner, write the following:2 139 /a>2 140 /a> tmp_a = ACCESS_ONCE(a);2 141 a> do_something_with(tmp_a);2 142 /a> do_something_else_with(tmp_a);2 143 /a>2 144 /a>For a fipal example, consider the following code, assuming that the2 145 /a>4.riable a is set at boot time before the second CPU is brought online2 146 /a>and never changed later, so that memory barriers are not needed:2 147 /a>2 148 a> if (a)2 149 /a> b = 9;2 15> a> else2 151 /a> b = 42;2 152 /a>2 153 /a>The comp/ler is within its rights to manufacture an addi 154 /a>by transforming the above code into the following:2 155 /a>2 156 /a> b = 42;2 157 a> if (a)2 158 /a> b = 9;2 159 /a>2 160 /a>This could come as a fatal surprise to other code running concurrently2 161 /a>that expected b to never have the 4.3ue 42 if a was zero. To prevent2 162 /a>the comp/ler from doing this, write something like:2 163 /a>2 164 /a> if (a)2 165 a> ACCESS_ONCE(b) = 9;2 166 a> else2 167 a> ACCESS_ONCE(b) = 42;2 168 /a>2 169 /a>Don't even -think- about doing this without proper use of memory barriers,2 17> a>locks, or atomic opera 171 /a>2 172 /a>*** WARNING: ACCESS_ONCE() DOES NOT IMPLY A BARRIER! ***2 173 /a>2 174 a>Now, we move onto the atomic opera 175 a>the help of assembly code.2 176 /a>2 177 a> void atomic_add(int i, atomic_t *v);2 178 a> void atomic_sub(int i, atomic_t *v);2 179 a> void atomic_inc(atomic_t *v);2 180 a> void atomic_dec(atomic_t *v);2 181 /a>2 182 /a>These four routines add and subtract integral 4.3ues to/from the given2 183 /a>atomic_t va3ue. The first two routines pass explicit integers by2 184 /a>which to make the adjustment, whereas the latter two use an implicit2 185 /a>adjustment 4.3ue of "1".2 186 /a>2 187 /a>One very important aspect of these two routines is that they DO NOT2 188 /a>require any explicit memory barriers. They need only perform the2 189 /a>atomic_t counter update in an SMP safe manner.2 19> a>2 191 /a>Next, we have:2 192 /a>2 193 /a> int atomic_inc_return(atomic_t *v);2 194 /a> int atomic_dec_return(atomic_t *v);2 195 /a>2 196 /a>These routines add 1 and subtract 1, respect/vely, from the given2 197 a>atomic_t and return the new counter 4.3ue after the opera 198 /a>performed.2 199 /a>2 200 a>Unlike the above routines, it is required that explicit memory2 201 /a>barriers are performed before and after the opera 202 /a>done such that all memory opera 203 /a>opera 204 /a>opera 205 /a>2 206 /a>For example, it should behave as if a smp_mb() call existed both2 207 /a>before and after the atomic opera 208 /a>2 209 /a>If the atomic instruct/ops used in an implementa 2i> a>memory barrier seman 211 /a>fine as well.2 212 /a>2 213 /a>Let's move on:2 214 /a>2 215 a> int atomic_add_return(int i, atomic_t *v);2 216 a> int atomic_sub_return(int i, atomic_t *v);2 217 /a>2 218 /a>These behave just like atomic_{inc,dec}_return() except that an2 219 /a>explicit counter adjustment is given instead of the implicit "1".2 220 /a>This means that like atomic_{inc,dec}_return(), the memory barrier2 221 /a>seman 222 /a>2 223 /a>Next:2 224 /a>2 225 a> int atomic_inc_and_test(atomic_t *v);2 226 a> int atomic_dec_and_test(atomic_t *v);2 227 /a>2 228 /a>These two routines increment and decrement by 1, respect/vely, the2 229 /a>given atomic counter. They return a boolean indicating whether the2 23> a>resulting counter 4.3ue was zero or not.2 231 /a>2 232 /a>It requires explicit memory barrier seman 233 /a>above.2 234 /a>2 235 a> int atomic_sub_and_test(int i, atomic_t *v);2 236 /a>2 237 a>This is iden 238 a>decrement is given instead of the implicit "1". It requires explicit2 239 /a>memory barrier seman 24> a>2 241 a> int atomic_add_negat/ve(int i, atomic_t *v);2 242 /a>2 243 /a>The given increment is added to the given atomic counter va3ue. A2 244 /a>boolean is return which indicates whether the resulting counter 4.3ue2 245 /a>is negat/ve. It requires explicit memory barrier seman 246 /a>opera 247 /a>2 248 /a>Then:2 249 /a>2 25> a> int atomic_xchg(atomic_t *v, int new);2 251 /a>2 252 /a>This performs an atomic exchange opera 253 /a>the given new va3ue. It returns the old 4.3ue that the atomic 4.riable v had 254 /a>just before the opera 255 /a>2 256 a> int atomic_cmpxchg(atomic_t *v, int old, int new);2 257 /a>2 258 /a>This performs an atomic compare exchange opera 259 /a>with the given old d latew va3ues= L5"Documenta2160 /a>This could come a2 a fa2al surt old, int new2161 /a>that expected b t2 neve2 have y2 162 /a>the comp/ler from2doing26tomic_ops.txt#L243" id="L243" class="line" name="L163">2163 /a>22164 /a> if (a)22165 a> A2CESS_2NCE(b)Tef="Documentaet(). The int new 266 /a>2 167 a> A2CESS_26tomic_ops.txt#L258" id="L258" class="line" name="L168">2168 /a>22169 /a>Don't even -t2ink- 26tomic_ops.txt#L250" id="L250" class="line" name="L170">217> a>locks, or atomic 2pera<27tomic_t *v, int new);22171 /a>22172 /a>*** WARNING: ACCE2S_ONC27 that do_somenta2173 /a>22174 a>Now, we move onto2the a2omic ora2175 a>the help of assem2ly co27tomic_ops.txt#L256" id="L256" class="line" name="L176">2176 /a>2 277 a> #define ATOMESS_2int i,unlocu2178 a> void atom2c_sub27tomic_ops.txt#L209" id="L209" class="line" name="L179">2179 a> void atom2c_inc27n an SMP safhrefmay_umen, loaded frpt that an v);2unlocu)v,o1,mic_ops.txt#L112" id="L112" class="line" na2e="L180">2180 a> void atom2c_dec28tomic_ops.txt#L241" id="L241" class="line" name="L181">2181 /a>22182 /a>These four routin2s add28 that doacumenp/ler seman2183 /a>atomic_t va3ue. 2he fi28gly ordered witsultin"Documentether thep/ato,2184 /a>which to make the2adjus2ment, a href="sultin="Douiresnotherc_ops.txt#L249" id="L249" class="line" name="L185">2185 /a>adjustment 4.3ue 2f &qu28tomic_ops.txt#L256" id="L256" class="line" name="L186">2186 /a>22187 /a>One very importan2 aspe28nt i, atomic_t *v)href="__ href_hat an exp( 288 a> #define atom_sub28nt i, atomic_t *v)href="__"Docum_hat an umen2189 /a>atomic_t counter 2pdate28tomic_t *v);2219> a>22191 /a>Next, we have:22192 /a>22193 /a> int atomi2_inc_2eturn(atomic_tobjta2194 /a> int atomi2_dec_2eturn(atomic_thref="__"Docum_hat an exp()c_ops.txt#L257" id="L257" class="line" name="L185">2195 /a>22196 /a>These routines ad2 1 an29tomic_ops.txt#L237" id="L237" class="line" name="L197">2197 a>atomic_t and retu2n the2new co/op/ak 2198 /a>performed.22199 /a>23200 a>Unlike the above 3outin3s, it plicit23291 /a>Next, we have:23202 /a>done such that al3 memo3atomic_ops.txt#L103" id="L103" class="line" na3e="L203">3203 /a>opera3204 /a>opera3295 /a>23296 /a>These routines ad3ould 30tomic_ops.txt#L237" id="L237" class="line" na3e="L207">3207 /a>before and after 3he at307E(b)Tef=o the usereeed with23208 /a>23299 /a>232i> a>memory barrier se3an3211 /a>fine as well.23212 /a>23213 /a>Let's move on323214 /a>23215 a> int atomi3_add_3eturn(k="nelat theismenta3216 a> int atomi3_sub_3eturn(ta3217 /a>23218 /a>These behave just3like 31tomic_ops.txt#L209" id="L209" class="line" na3e="L219">3219 /a>explicit counter 3djust3ent ised o3220 /a>This means that l3ke at3mic_{i{_ops.txt#L237" id="L237" class="line" na3e="L211">3221 /a>seman3222 /a>23223 /a>Next:23224 /a>23225 a> int atomi3_inc_3nd_tesed o3226 a> int atomi3_dec_3nd_tes{_ops.txt#L237" id="L237" class="line" na3e="L217">3227 /a>23228 /a>These two routine3 incr3ef="Documenta3229 /a>given atomic coun3er. 3hey re}_ops.txt#L257" id="L257" class="line" na3e="L230">323> a>resulting counter34.3ue3atomic_ops.txt#L131" id="L131" class="line" na3e="L231">3231 /a>23232 /a>It requires expli3it me3ory ba{_ops.txt#L237" id="L237" class="line" na3e="L233">3233 /a>above.23234 /a>23235 a> int atomi3_sub_3nd_tes}_ops.txt#L257" id="L257" class="line" na3e6"L204">3236 /a>23237 a>This is iden3238 a>decrement is give3 inst3ad of {_ops.txt#L237" id="L237" class="line" na3e="L219">3239 /a>memory barrier se3an324> a>23241 a> int atomi3_add_34tomic_ops.txt#L182" id="L182" class="line" na3e="L242">3242 /a>23243 /a>The given increme3t is 343ng();23244 /a>boolean is return3which344ng();23245 /a>is negat/ve. It 3equir34d_test(int i,}_ops.txt#L257" id="L257" class="line" na3e="L246">3246 /a>opera3247 /a>23248 /a>Then:23249 /a>2325> a> int atomi3_xchg35ic_{i{_ops.txt#L237" id="L237" class="line" na3e="L251">3251 /a>23252 /a>This performs an 3tomic3atomic_ops.txt#L153" id="L153" class="line" na3e="L253">3253 /a>the given new va33e. I353ng();23254 /a>just before the o3era3255 /a>23256 a> int atomi3_cmpx35tomic_ops.txt#L237" id="L237" class="line" na3e="L257">3257 /a>23258 /a>This performs an 3tomic3a href="Documenta3259 /a>with the given ol3 d la35 href="Documenta3160 /a>This could come a3 a fa36CE(a);23161 /a>that expected b t3 neve361_test(int i,}_ops.txt#L257" id="L257" class="line" na3"="L252">3162 /a>the comp/ler from3doing36tomic}_ops.txt#L257" id="L257" class="line" na3"="L253">3163 /a>23164 /a> if (a)23165 a> A3CESS_3NCE(b){_ops.txt#L237" id="L237" class="line" na3e"L26"> 366 /a>23167 a> A3CESS_3NCE(b) = 42;23168 /a>23169 /a>Don't even -t3ink- 36tomic_ops.txt#L250" id="L250" class="line" na3e="L170">317> a>locks, or atomic 3pera<37tomic_t *v, intomiat an explicit23171 /a>23172 /a>*** WARNING: ACCE3S_ONC37tomic}_ops.txt#L257" id="L257" class="line" na3e="L173">3173 /a>23174 a>Now, we move onto3the a3omic o(c_and_tea squirefocumeref=do_somARP queuop/atag hrefer ghts_ops.txt#L174" id="L174" class="line" na3e="L165">3175 a>the help of assem3ly co37tomic generic neighbintediscova href="=do_somnetworking. Olaf Kircc_ops.txt#L207" id="L207" class="line" na3e="L176">3176 /a>2 377 a> #define AT3MESS_3int i, ing:2at an und the23178 a> void atom3c_sub37tomic_ops.txt#L209" id="L209" class="line" na3e="L179">3179 a> void atom3c_inc37n an Gcumens23180 a> void atom3c_dec38tomic3181 /a>23182 /a>These four routin3s add38tomic_ops.txt#L153" id="L153" class="line" na3e="L183">3183 /a>atomic_t va3ue. 3he fi38gly oO23184 /a>which to make the3adjus3ment, bf="Dt,usius triggc2entaref="saermerefinpobj_deto ty") explicerro/_ops.txt#L237" id="L237" class="line" na3e="L185">3185 /a>adjustment 4.3ue 3f &qu38tomicsp/aence looks requirerc_ops.txt#L249" id="L249" class="line" na3e="L186">3186 /a>23187 /a>One very importan3 aspe38nt i, atomic_cpu 0;2388 a> #define at3m_sub38f="Documenta3189 /a>atomic_t counter 3pdate38tomic_t *v);2obj =r/bj_l/oprpeek()c_ops.txt#L257" id="L257" class="line" na3e="L190">319> a>23191 /a>Next, we have:23192 /a>23193 /a> int atomi3_inc_393ng();23194 /a> int atomi3_dec_394ng();23195 /a>23196 /a>These routines ad3 1 an39umenta3197 a>atomic_t and retu3n the397omic_t *v, i... umtc to dr"lientl0i..._ops.txt#L257" id="L257" class="line" na3e="L258">3198 /a>performed.23199 /a>24200 a>Unlike the above 4outin40tomic_t *v, istill="D hres oic_ops.txt#L146" id="L146" class="line" na4e1"L200">4291 /a>Next, we have:24202 /a>done such that al4 memo4atomic_ops.txt#L103" id="L103" class="line" na4e="L203">4203 /a>opera4294 /a> int atomi44295 /a>24296 /a>These routines ad4ould 40turn(tae" naass="line" name="L236"> 236 /a>231984/a>2 2094/a>232004 a>memory4barrier se3an32004 a>Next, w well.232004 a>done suf="Documen3a4295 /a>Let"s move on324295 /a> f="Documen3a21844 a> 4 int atomi3_add_3eturn(k4"nela4 theisindexhref=unlbaop/aupp/atomicddr atoune atomic2<_opsbeeref.txt#L" id="L25" class="line" name3e"L27"> 377 4 a> 4 int atomi3_sub_3eturn(t4e" na/a>231984/a>These 4ehave just3like 31tomic_4ps.tx4#L209" id="L209" class="line" na3e="L219">32194/a>explic4t counter 3djust3ent ise4 o21844/a>This m4ans that l3ke at3mic_{i{4ops.t4t#L237extentb31984/a>seman<4cs are req3ired.321urn(a4omic_42L182" id="L182" class="line" na3e="L242">32424/a>232424/a>Let"a href="Do3ument332424/a> f="Documen3a 2344 a> 4 int atomi3_inc_3nd_tese4 o21864 a> 4 int atomi3_dec_3nd_tes{4ops.t4t#L237Naa hilmic_opsb tref=ra 377 4/a>232424/a>These 4wo routine3 incr3ef="Doc4menta4objta32914/a>given 4tomic coun3er. 3hey re}4ops.t4t#L257naa hilLndi#L19atoune atocpu" id="L234" class="line" name="L234"> 2344 a>result4ng counter34.3ue3atomic_4ps.tx4#L131" id="L131" class="line" na3e="L231">32314/a>231924/a>It req4ires expli3it me3ory ba{4ops.t432ta31924/a>Let"31924/a> f="Documen3a 2354 a> 4 int atomi3_sub_3nd_tes}4ops.t43mentaet(ly, from thegc2entxt#L,t an tef="Dtomic_ops.txt#L229"sb trnumb3" id="L103" class="line" na4e5"L203">4295 /a>2 2204 a>This i4 iden21684 a>decrem4nt is give3 inst3ad of {4ops.t43.txt#L24yased 2214/a>memory4barrier se3an 2204 a>2 2414 a> 4 int atomi3_add_34tomic_4ps.tx4 atomic_t *v);231924/a>231924/a>The gi4en increme3t is 343ng();431924/a>boolea4 is return3which344ng();4 2354/a>is neg4t/ve. It 3equir34d_test4int i4}_ops.Lexplicit memo,/op/atomic_optt(ly, from theref="Documenta 2354/a>2 2354/a>This i4f="Documen3a21754/a>Then:24a href="Do3ument34tomic_4ps.tx4#L209" id="L209" class="line" na3e="L249">32494/a>221604 a> 4 int atomi3_xchg35ic_{i{4ops.t4t#L237iepst#L2200ic c_opprf="Documenta 2014/a>2 2014/a>221754/a>the gi4en new va33e. I353ng();431744/a>just b4fore the o3era31744/a>is neg4f="Documen3a31754 a> 4 int atomi3_cmpx35tomic_4ps.tx4#L237"uptxtp32-b tsic ume#L20a21754/0" class=" class="line" na3e="L254a 2584/a>This p4rforms an 3tomic3a href=4Docum4nta 2584/a>2 2584/a>This c4uld come a3 a fa36CE(a);432004/a>that e4pected b t3 neve361_test4int i4}_ops..txt#L249t#L211txt#L212" id="L212" class="line" name="L212"> 2124/a>the co4p/ler from3doing36tomic}4ops.t4#L243" id="L243" class="line" name="L163">21634/a>221604/a> 4 if (a)231844 a> 4 A3CESS_3NCE(b){4ops.t4t#L237c231744a>2 2124/0" class= A3CESS_3NCE(b) 4 42;24/bj_l/Lexp thee if i/the imb tref=ra 2124/a>This p4f="Documen3a31864/a>Don"t even -t3ink- 36tomic_4ps.tx4#L250" id="L250" class="line" na3e="L170">317>4 a>locks,4or atomic 3pera<37tomic_4 *v, 4ntomiat an exp 1c_ops.txt#L257" id="L257" class="line" name="L184">21944/a>231714/a>*** WA4NING: ACCE3S_ONC37tomic}4ops.t47="Documpppppppppppppp/*dr"li*/" id="L257" class="line" name="L184">21944/a>221944/a> 4 move onto3the a3omic o(4_and_47L235" id="L235" class="line" name="L235"> 2354 a>the he4p of assem3ly co37tomic 4eneri47mentaet()u232424/a>232424/0" class=#define AT3MESS_3int i, 4ng:2a4 an unj l/op deL20s.txthet_b t()#cu232424/a>This p4 void atom3c_sub37tomic_4ps.tx4#L209"c232424/a>Don" void atom3c_inc37n an G4umens4 2124 a> 4 void atom3c_dec38tomic<4 href4#L241" id="L241" class="line" name="L181">21814/a>231864/a>These 4our routin3s add38tomic_4ps.tx4#L153" id="L153" class="line" na3e="L183">31834/a>atomic4t va3ue. 3he fi38gly oO431924/a>which 4o make the3adjus3ment, b4="Dt,48L235" id="L235" class="line" name="L235"> 2354/a>adjust4ent 4.3ue 3f &qu38tomics4/aenc4 looksWops.,ns2 2354/a>2 2204/a>One ve4y importan3 aspe38nt i, 4tomic48L258" id="L258" class="line" name="L258"> 2584a> 4#define at3m_sub38f="Doc4menta4obj_poIfe2 2354/a>atomic4t counter 3pdate38tomic_4 *v);4obj =r thep/ato, 2354 a>231864/a>Next, 4e have:232424/a>2219>4/a> 4 int atomi3_inc_393ng();4219>4/a>which 4 int atomi3_dec_394ng();4 2354/a>2 2354/a>231864 a>atomic4t and retu3n the397omic_4 *v, 49L258" id="L258" class="line" name="L258"> 2584/a>perfor4ed.231844/a>2 2205 a>Unlike5the above 4outin40tomic_5 *v, 5still="D hres i*/ id="L220" class="line" name="L220"> 2205 1>Unlike5t have:2219>5/a>done s5ch that al4 memo4atomic_5ps.tx502ta219>5/3>done s5cint atomi3_inc_393ng();5riocu50L174" id="L174" class="line" na3e="L174">31745/a> 5 int atomi432995/a>2 2205/a>These 5outines ad4ould 40turn(t5 2205 7>These 5o and retu3n the397omic_5href=50.. umtc to d_hat an exp()S_txt#L_b t(7" id="L257" class="line" name="L190">219>5/8>These 5od.2 2095/a>221605 a>memory5barrier se3an21605 1>Unlike5 well.221605 a>done s5f="Documen3a21735/a>Let#s move on32 2205/a> 5f="Documen3a 2355 a> 5 int atomi3_add_3eturn(k5"nela515v);231925 a> 5 int atomi3_sub_3eturn(t531925 7>These 5f="Documen3a31925 8>These 5ehave just3like 31tomic_5ps.tx5#L209" id="L209" class="line" na3e="L219">32195/a>explic5t counter 3djust3ent ise5 o32005/a>This m5ans that l3ke at3mic_{i{5ops.t5t#L237ob"D_l nta32005/1>Unlike5cs are req3ired.321urn(a5omic_52L182"teed with2b tsi#L174"swor2" id="L222" class="line" na3e="L182">31825/a>231835/a>Let#a href="Do3ument331835/a> 5f="Documen3a31835/a> 5 int atomi3_inc_3nd_tese5 o31835/a> 5 int atomi3_dec_3nd_tes{5ops.t5t#L237expexsivL1non-na3e=" cedllowing:maysoc_ops.t#L174"su231825/7>These 5f="Documen3a31825/8>These 5wo routine3 incr3ef="Doc5menta5objta31825/a>explic5tomic coun3er. 3hey re}5ops.t52L250" id="L250" class="line" na3e="L170">317>5 a>result5ng counter34.3ue3atomic_5ps.tx530*v)href="__ href___het_b t(unsign" ps.tx n"e vollinps.txsign" ps.tx *cddr7" id="L257" class="line" na3e="L192">31925/a>231925/a>It req5ires expli3it me3ory ba{5ops.t532ta31925/a>Let#31925/a> 5f="Documen3a31925/a> 5 int atomi3_sub_3nd_tes}5ops.t535v);231925/a> 5f="Documen3a32375 a>This i5 iden 2355 a>decrem5nt is give3 inst3ad of {5ops.t53.txt#nta 2355 a>explic5barrier se3an317>5 a>2 2=" varimics alut"i_ops.1s="line" na3e="Ln 5 e=" cedllowing:maysoc_ope/o53ntg coulea4 is retumen3a<31tomic_hreoaxplici fro37Naa hilmic_op thi.txt#L103",ta 2354/a>This i4f="Docum5n3a21754/a>Then:24a href="5o3ume5t34tomic_4ps.tx4#L209" id="L209" class="line" 5a3e="L2495>32494/a>2 2014/a>232004/a>that e4pected b5t3 ne5e361_ta hilLndor421735/a>Let#s move 6n32 a);5origc"4o LXR softw3xt#byriocuc_ops.txthttp://sourcf="">LXR communitynd_t =rref=es{5ri2" id2axt#L_b tbyrc_ops.txtmailto:lxr@">lxr@ ux.nond_t.
5GDfooter"> lxr. kindcumhos.tx4#L2c_ops.txthttp://www.toopRoop