Home | History | Annotate | Download | only in bits
      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 
     36 namespace 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
     46 namespace __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