1// -*- C++ -*- header. 2 3// Copyright (C) 2008, 2009, 2010, 2011 4// Free Software Foundation, Inc. 5// 6// This file is part of the GNU ISO C++ Library. This library is free 7// software; you can redistribute it and/or modify it under the 8// terms of the GNU General Public License as published by the 9// Free Software Foundation; either version 3, or (at your option) 10// any later version. 11 12// This library is distributed in the hope that it will be useful, 13// but WITHOUT ANY WARRANTY; without even the implied warranty of 14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15// GNU General Public License for more details. 16 17// Under Section 7 of GPL version 3, you are granted additional 18// permissions described in the GCC Runtime Library Exception, version 19// 3.1, as published by the Free Software Foundation. 20 21// You should have received a copy of the GNU General Public License and 22// a copy of the GCC Runtime Library Exception along with this program; 23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24// <http://www.gnu.org/licenses/>. 25 26/** @file bits/atomic_2.h 27 * This is an internal header file, included by other library headers. 28 * Do not attempt to use it directly. @headername{atomic} 29 */ 30 31#ifndef _GLIBCXX_ATOMIC_2_H 32#define _GLIBCXX_ATOMIC_2_H 1 33 34#pragma GCC system_header 35 36namespace std _GLIBCXX_VISIBILITY(default) 37{ 38_GLIBCXX_BEGIN_NAMESPACE_VERSION 39 40// 2 == __atomic2 == Always lock-free 41// Assumed: 42// _GLIBCXX_ATOMIC_BUILTINS_1 43// _GLIBCXX_ATOMIC_BUILTINS_2 44// _GLIBCXX_ATOMIC_BUILTINS_4 45// _GLIBCXX_ATOMIC_BUILTINS_8 46namespace __atomic2 47{ 48 /// atomic_flag 49 struct atomic_flag : public __atomic_flag_base 50 { 51 atomic_flag() = default; 52 ~atomic_flag() = default; 53 atomic_flag(const atomic_flag&) = delete; 54 atomic_flag& operator=(const atomic_flag&) = delete; 55 atomic_flag& operator=(const atomic_flag&) volatile = delete; 56 57 // Conversion to ATOMIC_FLAG_INIT. 58 atomic_flag(bool __i): __atomic_flag_base({ __i }) { } 59 60 bool 61 test_and_set(memory_order __m = memory_order_seq_cst) 62 { 63 // Redundant synchronize if built-in for lock is a full barrier. 64 if (__m != memory_order_acquire && __m != memory_order_acq_rel) 65 __sync_synchronize(); 66 return __sync_lock_test_and_set(&_M_i, 1); 67 } 68 69 bool 70 test_and_set(memory_order __m = memory_order_seq_cst) volatile 71 { 72 // Redundant synchronize if built-in for lock is a full barrier. 73 if (__m != memory_order_acquire && __m != memory_order_acq_rel) 74 __sync_synchronize(); 75 return __sync_lock_test_and_set(&_M_i, 1); 76 } 77 78 void 79 clear(memory_order __m = memory_order_seq_cst) 80 { 81 __glibcxx_assert(__m != memory_order_consume); 82 __glibcxx_assert(__m != memory_order_acquire); 83 __glibcxx_assert(__m != memory_order_acq_rel); 84 85 __sync_lock_release(&_M_i); 86 if (__m != memory_order_acquire && __m != memory_order_acq_rel) 87 __sync_synchronize(); 88 } 89 90 void 91 clear(memory_order __m = memory_order_seq_cst) volatile 92 { 93 __glibcxx_assert(__m != memory_order_consume); 94 __glibcxx_assert(__m != memory_order_acquire); 95 __glibcxx_assert(__m != memory_order_acq_rel); 96 97 __sync_lock_release(&_M_i); 98 if (__m != memory_order_acquire && __m != memory_order_acq_rel) 99 __sync_synchronize(); 100 } 101 }; 102 103 104 /// Base class for atomic integrals. 105 // 106 // For each of the integral types, define atomic_[integral type] struct 107 // 108 // atomic_bool bool 109 // atomic_char char 110 // atomic_schar signed char 111 // atomic_uchar unsigned char 112 // atomic_short short 113 // atomic_ushort unsigned short 114 // atomic_int int 115 // atomic_uint unsigned int 116 // atomic_long long 117 // atomic_ulong unsigned long 118 // atomic_llong long long 119 // atomic_ullong unsigned long long 120 // atomic_char16_t char16_t 121 // atomic_char32_t char32_t 122 // atomic_wchar_t wchar_t 123 // 124 // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 125 // 8 bytes, since that is what GCC built-in functions for atomic 126 // memory access expect. 127 template<typename _ITp> 128 struct __atomic_base 129 { 130 private: 131 typedef _ITp __int_type; 132 133 __int_type _M_i; 134 135 public: 136 __atomic_base() = default; 137 ~__atomic_base() = default; 138 __atomic_base(const __atomic_base&) = delete; 139 __atomic_base& operator=(const __atomic_base&) = delete; 140 __atomic_base& operator=(const __atomic_base&) volatile = delete; 141 142 // Requires __int_type convertible to _M_i. 143 constexpr __atomic_base(__int_type __i): _M_i (__i) { } 144 145 operator __int_type() const 146 { return load(); } 147 148 operator __int_type() const volatile 149 { return load(); } 150 151 __int_type 152 operator=(__int_type __i) 153 { 154 store(__i); 155 return __i; 156 } 157 158 __int_type 159 operator=(__int_type __i) volatile 160 { 161 store(__i); 162 return __i; 163 } 164 165 __int_type 166 operator++(int) 167 { return fetch_add(1); } 168 169 __int_type 170 operator++(int) volatile 171 { return fetch_add(1); } 172 173 __int_type 174 operator--(int) 175 { return fetch_sub(1); } 176 177 __int_type 178 operator--(int) volatile 179 { return fetch_sub(1); } 180 181 __int_type 182 operator++() 183 { return __sync_add_and_fetch(&_M_i, 1); } 184 185 __int_type 186 operator++() volatile 187 { return __sync_add_and_fetch(&_M_i, 1); } 188 189 __int_type 190 operator--() 191 { return __sync_sub_and_fetch(&_M_i, 1); } 192 193 __int_type 194 operator--() volatile 195 { return __sync_sub_and_fetch(&_M_i, 1); } 196 197 __int_type 198 operator+=(__int_type __i) 199 { return __sync_add_and_fetch(&_M_i, __i); } 200 201 __int_type 202 operator+=(__int_type __i) volatile 203 { return __sync_add_and_fetch(&_M_i, __i); } 204 205 __int_type 206 operator-=(__int_type __i) 207 { return __sync_sub_and_fetch(&_M_i, __i); } 208 209 __int_type 210 operator-=(__int_type __i) volatile 211 { return __sync_sub_and_fetch(&_M_i, __i); } 212 213 __int_type 214 operator&=(__int_type __i) 215 { return __sync_and_and_fetch(&_M_i, __i); } 216 217 __int_type 218 operator&=(__int_type __i) volatile 219 { return __sync_and_and_fetch(&_M_i, __i); } 220 221 __int_type 222 operator|=(__int_type __i) 223 { return __sync_or_and_fetch(&_M_i, __i); } 224 225 __int_type 226 operator|=(__int_type __i) volatile 227 { return __sync_or_and_fetch(&_M_i, __i); } 228 229 __int_type 230 operator^=(__int_type __i) 231 { return __sync_xor_and_fetch(&_M_i, __i); } 232 233 __int_type 234 operator^=(__int_type __i) volatile 235 { return __sync_xor_and_fetch(&_M_i, __i); } 236 237 bool 238 is_lock_free() const 239 { return true; } 240 241 bool 242 is_lock_free() const volatile 243 { return true; } 244 245 void 246 store(__int_type __i, memory_order __m = memory_order_seq_cst) 247 { 248 __glibcxx_assert(__m != memory_order_acquire); 249 __glibcxx_assert(__m != memory_order_acq_rel); 250 __glibcxx_assert(__m != memory_order_consume); 251 252 if (__m == memory_order_relaxed) 253 _M_i = __i; 254 else 255 { 256 // write_mem_barrier(); 257 _M_i = __i; 258 if (__m == memory_order_seq_cst) 259 __sync_synchronize(); 260 } 261 } 262 263 void 264 store(__int_type __i, memory_order __m = memory_order_seq_cst) volatile 265 { 266 __glibcxx_assert(__m != memory_order_acquire); 267 __glibcxx_assert(__m != memory_order_acq_rel); 268 __glibcxx_assert(__m != memory_order_consume); 269 270 if (__m == memory_order_relaxed) 271 _M_i = __i; 272 else 273 { 274 // write_mem_barrier(); 275 _M_i = __i; 276 if (__m == memory_order_seq_cst) 277 __sync_synchronize(); 278 } 279 } 280 281 __int_type 282 load(memory_order __m = memory_order_seq_cst) const 283 { 284 __glibcxx_assert(__m != memory_order_release); 285 __glibcxx_assert(__m != memory_order_acq_rel); 286 287 __sync_synchronize(); 288 __int_type __ret = _M_i; 289 __sync_synchronize(); 290 return __ret; 291 } 292 293 __int_type 294 load(memory_order __m = memory_order_seq_cst) const volatile 295 { 296 __glibcxx_assert(__m != memory_order_release); 297 __glibcxx_assert(__m != memory_order_acq_rel); 298 299 __sync_synchronize(); 300 __int_type __ret = _M_i; 301 __sync_synchronize(); 302 return __ret; 303 } 304 305 __int_type 306 exchange(__int_type __i, memory_order __m = memory_order_seq_cst) 307 { 308 // XXX built-in assumes memory_order_acquire. 309 return __sync_lock_test_and_set(&_M_i, __i); 310 } 311 312 313 __int_type 314 exchange(__int_type __i, memory_order __m = memory_order_seq_cst) volatile 315 { 316 // XXX built-in assumes memory_order_acquire. 317 return __sync_lock_test_and_set(&_M_i, __i); 318 } 319 320 bool 321 compare_exchange_weak(__int_type& __i1, __int_type __i2, 322 memory_order __m1, memory_order __m2) 323 { return compare_exchange_strong(__i1, __i2, __m1, __m2); } 324 325 bool 326 compare_exchange_weak(__int_type& __i1, __int_type __i2, 327 memory_order __m1, memory_order __m2) volatile 328 { return compare_exchange_strong(__i1, __i2, __m1, __m2); } 329 330 bool 331 compare_exchange_weak(__int_type& __i1, __int_type __i2, 332 memory_order __m = memory_order_seq_cst) 333 { 334 return compare_exchange_weak(__i1, __i2, __m, 335 __calculate_memory_order(__m)); 336 } 337 338 bool 339 compare_exchange_weak(__int_type& __i1, __int_type __i2, 340 memory_order __m = memory_order_seq_cst) volatile 341 { 342 return compare_exchange_weak(__i1, __i2, __m, 343 __calculate_memory_order(__m)); 344 } 345 346 bool 347 compare_exchange_strong(__int_type& __i1, __int_type __i2, 348 memory_order __m1, memory_order __m2) 349 { 350 __glibcxx_assert(__m2 != memory_order_release); 351 __glibcxx_assert(__m2 != memory_order_acq_rel); 352 __glibcxx_assert(__m2 <= __m1); 353 354 __int_type __i1o = __i1; 355 __int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2); 356 357 // Assume extra stores (of same value) allowed in true case. 358 __i1 = __i1n; 359 return __i1o == __i1n; 360 } 361 362 bool 363 compare_exchange_strong(__int_type& __i1, __int_type __i2, 364 memory_order __m1, memory_order __m2) volatile 365 { 366 __glibcxx_assert(__m2 != memory_order_release); 367 __glibcxx_assert(__m2 != memory_order_acq_rel); 368 __glibcxx_assert(__m2 <= __m1); 369 370 __int_type __i1o = __i1; 371 __int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2); 372 373 // Assume extra stores (of same value) allowed in true case. 374 __i1 = __i1n; 375 return __i1o == __i1n; 376 } 377 378 bool 379 compare_exchange_strong(__int_type& __i1, __int_type __i2, 380 memory_order __m = memory_order_seq_cst) 381 { 382 return compare_exchange_strong(__i1, __i2, __m, 383 __calculate_memory_order(__m)); 384 } 385 386 bool 387 compare_exchange_strong(__int_type& __i1, __int_type __i2, 388 memory_order __m = memory_order_seq_cst) volatile 389 { 390 return compare_exchange_strong(__i1, __i2, __m, 391 __calculate_memory_order(__m)); 392 } 393 394 __int_type 395 fetch_add(__int_type __i, memory_order __m = memory_order_seq_cst) 396 { return __sync_fetch_and_add(&_M_i, __i); } 397 398 __int_type 399 fetch_add(__int_type __i, 400 memory_order __m = memory_order_seq_cst) volatile 401 { return __sync_fetch_and_add(&_M_i, __i); } 402 403 __int_type 404 fetch_sub(__int_type __i, memory_order __m = memory_order_seq_cst) 405 { return __sync_fetch_and_sub(&_M_i, __i); } 406 407 __int_type 408 fetch_sub(__int_type __i, 409 memory_order __m = memory_order_seq_cst) volatile 410 { return __sync_fetch_and_sub(&_M_i, __i); } 411 412 __int_type 413 fetch_and(__int_type __i, memory_order __m = memory_order_seq_cst) 414 { return __sync_fetch_and_and(&_M_i, __i); } 415 416 __int_type 417 fetch_and(__int_type __i, 418 memory_order __m = memory_order_seq_cst) volatile 419 { return __sync_fetch_and_and(&_M_i, __i); } 420 421 __int_type 422 fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst) 423 { return __sync_fetch_and_or(&_M_i, __i); } 424 425 __int_type 426 fetch_or(__int_type __i, 427 memory_order __m = memory_order_seq_cst) volatile 428 { return __sync_fetch_and_or(&_M_i, __i); } 429 430 __int_type 431 fetch_xor(__int_type __i, memory_order __m = memory_order_seq_cst) 432 { return __sync_fetch_and_xor(&_M_i, __i); } 433 434 __int_type 435 fetch_xor(__int_type __i, 436 memory_order __m = memory_order_seq_cst) volatile 437 { return __sync_fetch_and_xor(&_M_i, __i); } 438 }; 439 440 441 /// Partial specialization for pointer types. 442 template<typename _PTp> 443 struct __atomic_base<_PTp*> 444 { 445 private: 446 typedef _PTp* __pointer_type; 447 448 __pointer_type _M_p; 449 450 public: 451 __atomic_base() = default; 452 ~__atomic_base() = default; 453 __atomic_base(const __atomic_base&) = delete; 454 __atomic_base& operator=(const __atomic_base&) = delete; 455 __atomic_base& operator=(const __atomic_base&) volatile = delete; 456 457 // Requires __pointer_type convertible to _M_p. 458 constexpr __atomic_base(__pointer_type __p): _M_p (__p) { } 459 460 operator __pointer_type() const 461 { return load(); } 462 463 operator __pointer_type() const volatile 464 { return load(); } 465 466 __pointer_type 467 operator=(__pointer_type __p) 468 { 469 store(__p); 470 return __p; 471 } 472 473 __pointer_type 474 operator=(__pointer_type __p) volatile 475 { 476 store(__p); 477 return __p; 478 } 479 480 __pointer_type 481 operator++(int) 482 { return fetch_add(1); } 483 484 __pointer_type 485 operator++(int) volatile 486 { return fetch_add(1); } 487 488 __pointer_type 489 operator--(int) 490 { return fetch_sub(1); } 491 492 __pointer_type 493 operator--(int) volatile 494 { return fetch_sub(1); } 495 496 __pointer_type 497 operator++() 498 { return fetch_add(1) + 1; } 499 500 __pointer_type 501 operator++() volatile 502 { return fetch_add(1) + 1; } 503 504 __pointer_type 505 operator--() 506 { return fetch_sub(1) -1; } 507 508 __pointer_type 509 operator--() volatile 510 { return fetch_sub(1) -1; } 511 512 __pointer_type 513 operator+=(ptrdiff_t __d) 514 { return fetch_add(__d) + __d; } 515 516 __pointer_type 517 operator+=(ptrdiff_t __d) volatile 518 { return fetch_add(__d) + __d; } 519 520 __pointer_type 521 operator-=(ptrdiff_t __d) 522 { return fetch_sub(__d) - __d; } 523 524 __pointer_type 525 operator-=(ptrdiff_t __d) volatile 526 { return fetch_sub(__d) - __d; } 527 528 bool 529 is_lock_free() const 530 { return true; } 531 532 bool 533 is_lock_free() const volatile 534 { return true; } 535 536 void 537 store(__pointer_type __p, memory_order __m = memory_order_seq_cst) 538 { 539 __glibcxx_assert(__m != memory_order_acquire); 540 __glibcxx_assert(__m != memory_order_acq_rel); 541 __glibcxx_assert(__m != memory_order_consume); 542 543 if (__m == memory_order_relaxed) 544 _M_p = __p; 545 else 546 { 547 // write_mem_barrier(); 548 _M_p = __p; 549 if (__m == memory_order_seq_cst) 550 __sync_synchronize(); 551 } 552 } 553 554 void 555 store(__pointer_type __p, 556 memory_order __m = memory_order_seq_cst) volatile 557 { 558 __glibcxx_assert(__m != memory_order_acquire); 559 __glibcxx_assert(__m != memory_order_acq_rel); 560 __glibcxx_assert(__m != memory_order_consume); 561 562 if (__m == memory_order_relaxed) 563 _M_p = __p; 564 else 565 { 566 // write_mem_barrier(); 567 _M_p = __p; 568 if (__m == memory_order_seq_cst) 569 __sync_synchronize(); 570 } 571 } 572 573 __pointer_type 574 load(memory_order __m = memory_order_seq_cst) const 575 { 576 __glibcxx_assert(__m != memory_order_release); 577 __glibcxx_assert(__m != memory_order_acq_rel); 578 579 __sync_synchronize(); 580 __pointer_type __ret = _M_p; 581 __sync_synchronize(); 582 return __ret; 583 } 584 585 __pointer_type 586 load(memory_order __m = memory_order_seq_cst) const volatile 587 { 588 __glibcxx_assert(__m != memory_order_release); 589 __glibcxx_assert(__m != memory_order_acq_rel); 590 591 __sync_synchronize(); 592 __pointer_type __ret = _M_p; 593 __sync_synchronize(); 594 return __ret; 595 } 596 597 __pointer_type 598 exchange(__pointer_type __p, memory_order __m = memory_order_seq_cst) 599 { 600 // XXX built-in assumes memory_order_acquire. 601 return __sync_lock_test_and_set(&_M_p, __p); 602 } 603 604 605 __pointer_type 606 exchange(__pointer_type __p, 607 memory_order __m = memory_order_seq_cst) volatile 608 { 609 // XXX built-in assumes memory_order_acquire. 610 return __sync_lock_test_and_set(&_M_p, __p); 611 } 612 613 bool 614 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 615 memory_order __m1, memory_order __m2) 616 { 617 __glibcxx_assert(__m2 != memory_order_release); 618 __glibcxx_assert(__m2 != memory_order_acq_rel); 619 __glibcxx_assert(__m2 <= __m1); 620 621 __pointer_type __p1o = __p1; 622 __pointer_type __p1n = __sync_val_compare_and_swap(&_M_p, __p1o, __p2); 623 624 // Assume extra stores (of same value) allowed in true case. 625 __p1 = __p1n; 626 return __p1o == __p1n; 627 } 628 629 bool 630 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 631 memory_order __m1, memory_order __m2) volatile 632 { 633 __glibcxx_assert(__m2 != memory_order_release); 634 __glibcxx_assert(__m2 != memory_order_acq_rel); 635 __glibcxx_assert(__m2 <= __m1); 636 637 __pointer_type __p1o = __p1; 638 __pointer_type __p1n = __sync_val_compare_and_swap(&_M_p, __p1o, __p2); 639 640 // Assume extra stores (of same value) allowed in true case. 641 __p1 = __p1n; 642 return __p1o == __p1n; 643 } 644 645 __pointer_type 646 fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) 647 { return __sync_fetch_and_add(&_M_p, __d); } 648 649 __pointer_type 650 fetch_add(ptrdiff_t __d, 651 memory_order __m = memory_order_seq_cst) volatile 652 { return __sync_fetch_and_add(&_M_p, __d); } 653 654 __pointer_type 655 fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) 656 { return __sync_fetch_and_sub(&_M_p, __d); } 657 658 __pointer_type 659 fetch_sub(ptrdiff_t __d, 660 memory_order __m = memory_order_seq_cst) volatile 661 { return __sync_fetch_and_sub(&_M_p, __d); } 662 }; 663 664} // namespace __atomic2 665 666_GLIBCXX_END_NAMESPACE_VERSION 667} // namespace std 668 669#endif 670