There seems to be a significant amount of confusion around the new try_cmpxchg(), despite this being more like the C11 atomic_compare_exchange_*() family. Add a few words of clarification on how cmpxchg() and try_cmpxchg() relate to one another.
Unified · Split
| @@ -271,3 +271,44 @@ WRITE_ONCE. Thus: · 270 unmodified lines | |||
| 271 | SC *y, t; | 271 | SC *y, t; |
| 272 | 272 | ||
| 273 | is allowed. | 273 | is allowed. |
| 274 | |||
| 275 | |||
| 276 | CMPXCHG vs TRY_CMPXCHG | ||
| 277 | ---------------------- | ||
| 278 | |||
| 279 | int atomic_cmpxchg(atomic_t *ptr, int old, int new); | ||
| 280 | bool atomic_try_cmpxchg(atomic_t *ptr, int *oldp, int new); | ||
| 281 | |||
| 282 | Both provide the same functionality, but try_cmpxchg() can lead to more | ||
| 283 | compact code. The functions relate like: | ||
| 284 | |||
| 285 | bool atomic_try_cmpxchg(atomic_t *ptr, int *oldp, int new) | ||
| 286 | { | ||
| 287 | int ret, old = *oldp; | ||
| 288 | ret = atomic_cmpxchg(ptr, old, new); | ||
| 289 | if (ret != old) | ||
| 290 | *oldp = ret; | ||
| 291 | return ret == old; | ||
| 292 | } | ||
| 293 | |||
| 294 | and: | ||
| 295 | |||
| 296 | int atomic_cmpxchg(atomic_t *ptr, int old, int new) | ||
| 297 | { | ||
| 298 | (void)atomic_try_cmpxchg(ptr, &old, new); | ||
| 299 | return old; | ||
| 300 | } | ||
| 301 | |||
| 302 | Usage: | ||
| 303 | |||
| 304 | old = atomic_read(&v); old = atomic_read(&v); | ||
| 305 | for (;;) { do { | ||
| 306 | new = func(old); new = func(old); | ||
| 307 | tmp = atomic_cmpxchg(&v, old, new); } while (!atomic_try_cmpxchg(&v, &old, new)); | ||
| 308 | if (tmp == old) | ||
| 309 | break; | ||
| 310 | old = tmp; | ||
| 311 | } | ||
| 312 | |||
| 313 | NB. try_cmpxchg() also generates better code on some platforms (notably x86) | ||
| 314 | where the function more closely matches the hardware instruction. | ||