Knowledge

Fetch-and-add

Source 📝

251:: no process can interrupt the function mid-execution and hence see a state that only exists during the execution of the function. This code only serves to help explain the behaviour of fetch-and-add; atomicity requires explicit hardware support and hence can not be implemented as a simple high level function. 225:. However, in multiprocessor systems (even with interrupts disabled) two or more processors could be attempting to access the same memory at the same time. The fetch-and-add instruction allows any processor to atomically increment a value in memory, preventing such multiple processor collisions. 535:
project, which also produced a multiprocessor supporting fetch-and-add and containing custom VLSI switches that were able to combine concurrent memory references (including fetch-and-adds) to prevent them from serializing at the memory module containing the destination operand.
393:(it just wasn't called that then), and with the LOCK prefix, is atomic across multiple processors. However, it could not return the original value of the memory location (though it returned some flags) until the 277:
To implement a mutual exclusion lock, we define the operation FetchAndIncrement, which is equivalent to FetchAndAdd with inc=1. With this operation, a mutual exclusion lock can be implemented using the
389:
In the x86 architecture, the instruction ADD with the destination operand specifying a memory location is a fetch-and-add instruction that has been there since the
316:
myturn := FetchAndIncrement(&lock.ticketnumber) // must be atomic, since many threads might ask for a lock at the same time
116:
scheduled onto some single-core systems). The reason is that such an operation is actually implemented as multiple machine instructions:
336:* lock) { FetchAndIncrement(&lock.turn) // this need not be atomic, since only the possessor of the lock will execute this } 163:
and operate on that, then both store their results with the effect that one overwrites the other and the stored value becomes either
239:
operation. The fetch-and-add operation can solve the wait-free consensus problem for no more than two concurrent processes.
247:
The fetch-and-add instruction behaves like the following function. Crucially, the entire function is executed
96:
The motivation for having an atomic fetch-and-add is that operations that appear in programming languages as
718: 713: 374: 232: 550: 555: 36: 689: 606: 401: 367: 405: 378: 85: 32: 668: 601: 113: 565: 643: 70: 586: 8: 210: 101: 77: 46:
That is, fetch-and-add performs the following operation: increment the value at address
619: 105: 675: 408:
compiler, for both 32- and 64-bit x86 Intel platforms, based on extended asm syntax:
214: 349:
Integer datatype used in lock values can 'wrap around' when continuously incremented
623: 611: 545: 248: 236: 222: 81: 20: 339:
These routines provide a mutual-exclusion lock when following conditions are met:
228: 109: 40: 707: 532: 560: 615: 279: 346:
Number of tasks waiting for the lock does not exceed INT_MAX at any time
343:
Locktype data structure is initialized with function LockInit before use
669:"Intel Itanium Processor-specific Application Binary Interface (ABI)" 218: 151: 69:
in such a way that if this operation is executed by one process in a
304:* lock) { lock.ticketnumber := 0 lock.turn := 0 } 371: 363: 16:
CPU instruction to increment a value in memory by a given amount
73:
system, no other process will ever see an intermediate result.
270:
value := *location *location := value + inc
394: 390: 366:
standard. It is available as a proprietary extension to
100:
are not safe in a concurrent system, where multiple
705: 353: 62:is some value, and return the original value at 231:(1991) proved that fetch-and-add has a finite 377:specification, and (with the same syntax) in 605: 694:Using the GNU Compiler Collection (GCC) 584: 217:supported, it is sufficient to disable 76:Fetch-and-add can be used to implement 706: 108:are running concurrently (either in a 384: 531:Fetch-and-add was introduced by the 13: 14: 730: 696:. Free Software Foundation. 2005. 585:Herlihy, Maurice (January 1991). 397:introduced the XADD instruction. 242: 134:store register value back into 682: 661: 636: 594:ACM Trans. Program. Lang. Syst 578: 461:"lock; xaddl %0, %1" 1: 571: 354:Hardware and software support 39:increments the contents of a 7: 587:"Wait-free synchronization" 551:Load-link/store-conditional 539: 326:spin until lock is acquired 320:lock.turn ≠ myturn 235:number, in contrast to the 91: 10: 735: 526: 142:When one process is doing 254:<< atomic >> 150:concurrently, there is a 58:is a memory location and 644:"std::atomic::fetch_add" 410: 362:function appears in the 154:. They might both fetch 404:implementation for the 206:as might be expected. 43:by a specified value. 616:10.1145/114005.102808 566:Test and test-and-set 146:and another is doing 211:uniprocessor systems 719:Concurrency control 714:Computer arithmetic 400:The following is a 221:before accessing a 80:structures such as 78:concurrency control 506:"memory" 385:x86 implementation 690:"Atomic Builtins" 676:Intel Corporation 556:Read–modify–write 494:// input + output 292:ticketnumber 215:kernel preemption 726: 698: 697: 686: 680: 679: 673: 665: 659: 658: 656: 654: 648:cppreference.com 640: 634: 633: 631: 630: 609: 591: 582: 546:Compare-and-swap 522: 519: 516: 513: 510: 507: 504: 501: 500:// No input-only 498: 495: 492: 489: 486: 483: 480: 477: 474: 471: 468: 465: 462: 459: 456: 453: 450: 447: 444: 441: 438: 435: 432: 429: 426: 423: 420: 417: 414: 361: 237:compare-and-swap 223:critical section 205: 188: 175: 162: 149: 145: 137: 130: 124:into a register; 123: 99: 65: 61: 57: 53: 49: 21:computer science 734: 733: 729: 728: 727: 725: 724: 723: 704: 703: 702: 701: 688: 687: 683: 671: 667: 666: 662: 652: 650: 642: 641: 637: 628: 626: 589: 583: 579: 574: 542: 529: 524: 523: 520: 517: 514: 511: 508: 505: 502: 499: 496: 493: 490: 487: 484: 481: 478: 475: 472: 469: 466: 463: 460: 457: 454: 451: 448: 445: 442: 439: 436: 433: 430: 427: 424: 421: 418: 415: 412: 387: 359: 356: 337: 288:locktype { 275: 245: 229:Maurice Herlihy 196: 190: 183: 177: 170: 164: 161: 155: 147: 143: 135: 128: 121: 110:multi-processor 97: 94: 63: 59: 55: 51: 47: 41:memory location 17: 12: 11: 5: 732: 722: 721: 716: 700: 699: 681: 660: 635: 607:10.1.1.56.5659 600:(1): 124–149. 576: 575: 573: 570: 569: 568: 563: 558: 553: 548: 541: 538: 528: 525: 479:"+m" 467:"+r" 411: 386: 383: 355: 352: 351: 350: 347: 344: 312:* lock) { 284: 282:algorithm as: 253: 244: 243:Implementation 241: 194: 181: 168: 159: 140: 139: 132: 125: 93: 90: 15: 9: 6: 4: 3: 2: 731: 720: 717: 715: 712: 711: 709: 695: 691: 685: 677: 670: 664: 649: 645: 639: 625: 621: 617: 613: 608: 603: 599: 595: 588: 581: 577: 567: 564: 562: 559: 557: 554: 552: 549: 547: 544: 543: 537: 534: 533:Ultracomputer 422:fetch_and_add 409: 407: 403: 398: 396: 392: 382: 380: 376: 373: 369: 365: 348: 345: 342: 341: 340: 335: 331: 327: 323: 319: 315: 311: 307: 303: 299: 295: 291: 287: 283: 281: 273: 269: 265: 261: 257: 252: 250: 240: 238: 234: 230: 226: 224: 220: 216: 212: 207: 204: 200: 193: 187: 180: 174: 167: 158: 153: 133: 126: 119: 118: 117: 115: 111: 107: 103: 89: 87: 83: 79: 74: 72: 67: 44: 42: 38: 34: 30: 26: 25:fetch-and-add 22: 693: 684: 663: 651:. Retrieved 647: 638: 627:. Retrieved 597: 593: 580: 561:Test-and-set 530: 399: 388: 357: 338: 333: 329: 325: 321: 317: 313: 309: 305: 301: 297: 293: 289: 285: 276: 271: 267: 263: 259: 258:FetchAndAdd( 255: 246: 227: 208: 202: 198: 191: 185: 178: 172: 165: 156: 141: 131:to register; 114:preemptively 95: 75: 68: 45: 35:instruction 28: 24: 18: 280:ticket lock 266:inc) { 112:system, or 82:mutex locks 708:Categories 629:2007-05-20 572:References 358:An atomic 262:location, 249:atomically 219:interrupts 86:semaphores 71:concurrent 37:atomically 602:CiteSeerX 360:fetch_add 330:procedure 306:procedure 300:LockInit( 298:procedure 233:consensus 152:data race 148:x = x + b 144:x = x + a 102:processes 98:x = x + a 540:See also 488:variable 455:volatile 434:variable 334:locktype 310:locktype 302:locktype 274:value } 256:function 213:with no 92:Overview 54:, where 678:. 2001. 624:2181446 527:History 452:__asm__ 372:Itanium 370:in the 332:UnLock( 296:turn } 260:address 106:threads 653:1 June 622:  604:  512:return 416:inline 413:static 286:record 272:return 189:, not 23:, the 672:(PDF) 620:S2CID 590:(PDF) 515:value 473:value 443:value 364:C++11 318:while 308:Lock( 120:load 655:2015 391:8086 322:skip 127:add 84:and 612:doi 440:int 428:int 419:int 406:GCC 395:486 379:GCC 375:ABI 324:// 314:int 294:int 290:int 268:int 264:int 209:In 195:old 182:old 176:or 169:old 160:old 104:or 50:by 33:CPU 29:FAA 19:In 710:: 692:. 674:. 646:. 618:. 610:. 598:13 596:. 592:. 509:); 476:), 381:. 328:} 201:+ 197:+ 184:+ 171:+ 88:. 66:. 31:) 657:. 632:. 614:: 521:} 518:; 503:: 497:: 491:) 485:* 482:( 470:( 464:: 458:( 449:{ 446:) 437:, 431:* 425:( 402:C 368:C 203:b 199:a 192:x 186:b 179:x 173:a 166:x 157:x 138:. 136:x 129:a 122:x 64:x 60:a 56:x 52:a 48:x 27:(

Index

computer science
CPU
atomically
memory location
concurrent
concurrency control
mutex locks
semaphores
processes
threads
multi-processor
preemptively
data race
uniprocessor systems
kernel preemption
interrupts
critical section
Maurice Herlihy
consensus
compare-and-swap
atomically
ticket lock
C++11
C
Itanium
ABI
GCC
8086
486
C

Text is available under the Creative Commons Attribution-ShareAlike License. Additional terms may apply.