Home | History | Annotate | Download | only in stubs
      1 // Copyright 2014 Bloomberg Finance LP. All rights reserved.
      2 //
      3 // Redistribution and use in source and binary forms, with or without
      4 // modification, are permitted provided that the following conditions are
      5 // met:
      6 //
      7 //     * Redistributions of source code must retain the above copyright
      8 // notice, this list of conditions and the following disclaimer.
      9 //     * Redistributions in binary form must reproduce the above
     10 // copyright notice, this list of conditions and the following disclaimer
     11 // in the documentation and/or other materials provided with the
     12 // distribution.
     13 //     * Neither the name of Bloomberg Finance LP. nor the names of its
     14 // contributors may be used to endorse or promote products derived from
     15 // this software without specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 // This file is an internal atomic implementation, use atomicops.h instead.
     30 
     31 #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_
     32 #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_
     33 
     34 namespace google {
     35 namespace protobuf {
     36 namespace internal {
     37 
     38 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
     39                                          Atomic32 old_value,
     40                                          Atomic32 new_value) {
     41   Atomic32 result;
     42 
     43   asm volatile (
     44       "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
     45       "       cmpw %[cmp], %[res]             \n\t"  // compare values
     46       "       bne- 2f                         \n\t"
     47       "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
     48       "       bne- 1b                         \n\t"
     49       "2:                                     \n\t"
     50               : [res]  "=&b" (result)
     51               : [obj]  "b"   (ptr),
     52                 [cmp]  "b"   (old_value),
     53                 [val]  "b"   (new_value),
     54                 [zero] "i"   (0)
     55               : "cr0", "ctr");
     56 
     57   return result;
     58 }
     59 
     60 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
     61                                          Atomic32 new_value) {
     62   Atomic32 result;
     63 
     64   asm volatile (
     65       "1:     lwarx %[res], %[zero], %[obj]       \n\t"
     66       "       stwcx. %[val], %[zero], %[obj]      \n\t"
     67       "       bne- 1b                             \n\t"
     68               : [res]  "=&b" (result)
     69               : [obj]  "b"   (ptr),
     70                 [val]  "b"   (new_value),
     71                 [zero] "i"   (0)
     72               : "cr0", "ctr");
     73 
     74   return result;
     75 }
     76 
     77 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
     78                                           Atomic32 increment) {
     79   Atomic32 result;
     80 
     81   asm volatile (
     82       "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
     83       "       add %[res], %[val], %[res]      \n\t"  // add the operand
     84       "       stwcx. %[res], %[zero], %[obj]  \n\t"  // store old value
     85                                                      // if still reserved
     86       "       bne- 1b                         \n\t"
     87               : [res]  "=&b" (result)
     88               : [obj]  "b"   (ptr),
     89                 [val]  "b"   (increment),
     90                 [zero] "i"   (0)
     91               : "cr0", "ctr");
     92 
     93   return result;
     94 }
     95 
     96 inline void MemoryBarrier(void) {
     97   asm volatile (
     98       "       lwsync                          \n\t"
     99       "       isync                           \n\t"
    100               :
    101               :
    102               : "memory");
    103 }
    104 
    105 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
    106                                         Atomic32 increment) {
    107   Atomic32 result;
    108 
    109   asm volatile (
    110       "       lwsync                          \n\t"
    111 
    112       "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
    113       "       add %[res], %[val], %[res]      \n\t"  // add the operand
    114       "       stwcx. %[res], %[zero], %[obj]  \n\t"  // store old value
    115                                                      // if still reserved
    116       "       bne- 1b                         \n\t"
    117       "       isync                           \n\t"
    118               : [res]  "=&b" (result)
    119               : [obj]  "b"   (ptr),
    120                 [val]  "b"   (increment),
    121                 [zero] "i"   (0)
    122               : "cr0", "ctr");
    123 
    124   return result;
    125 }
    126 
    127 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
    128                                        Atomic32 old_value,
    129                                        Atomic32 new_value) {
    130   Atomic32 result;
    131 
    132   asm volatile (
    133       "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
    134       "       cmpw %[cmp], %[res]             \n\t"  // compare values
    135       "       bne- 2f                         \n\t"
    136       "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
    137       "       bne- 1b                         \n\t"
    138 
    139       "       isync                           \n\t"
    140       "2:                                     \n\t"
    141               : [res]  "=&b" (result)
    142               : [obj]  "b"   (ptr),
    143                 [cmp]  "b"   (old_value),
    144                 [val]  "b"   (new_value),
    145                 [zero] "i"   (0)
    146               : "cr0", "ctr");
    147 
    148   return result;
    149 }
    150 
    151 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
    152                                        Atomic32 old_value,
    153                                        Atomic32 new_value) {
    154   Atomic32 result;
    155 
    156   asm volatile (
    157       "       lwsync                          \n\t"
    158 
    159       "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
    160       "       cmpw %[cmp], %[res]             \n\t"  // compare values
    161       "       bne- 2f                         \n\t"
    162       "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
    163       "       bne- 1b                         \n\t"
    164 
    165       "2:                                     \n\t"
    166               : [res]  "=&b" (result)
    167               : [obj]  "b"   (ptr),
    168                 [cmp]  "b"   (old_value),
    169                 [val]  "b"   (new_value),
    170                 [zero] "i"   (0)
    171               : "cr0", "ctr");
    172 
    173   return result;
    174 }
    175 
    176 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
    177   *ptr = value;
    178 }
    179 
    180 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
    181   asm volatile (
    182       "       stw %[val], %[obj]      \n\t"
    183       "       isync                   \n\t"
    184               : [obj] "=m" (*ptr)
    185               : [val]  "b"  (value));
    186 }
    187 
    188 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
    189   asm volatile (
    190       "       lwsync                  \n\t"
    191       "       stw %[val], %[obj]      \n\t"
    192               : [obj] "=m" (*ptr)
    193               : [val]  "b"  (value));
    194 }
    195 
    196 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
    197   return *ptr;
    198 }
    199 
    200 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
    201   Atomic32 result;
    202 
    203   asm volatile (
    204       "1:     lwz %[res], %[obj]              \n\t"
    205       "       cmpw %[res], %[res]             \n\t" // create data
    206                                                     // dependency for
    207                                                     // load/load ordering
    208       "       bne- 1b                         \n\t" // never taken
    209 
    210       "       isync                           \n\t"
    211               : [res]  "=b" (result)
    212               : [obj]  "m"  (*ptr),
    213                 [zero] "i"  (0)
    214               : "cr0", "ctr");
    215 
    216   return result;
    217 }
    218 
    219 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
    220   Atomic32 result;
    221 
    222   asm volatile (
    223       "       lwsync                          \n\t"
    224 
    225       "1:     lwz %[res], %[obj]              \n\t"
    226       "       cmpw %[res], %[res]             \n\t" // create data
    227                                                     // dependency for
    228                                                     // load/load ordering
    229       "       bne- 1b                         \n\t" // never taken
    230               : [res]  "=b" (result)
    231               : [obj]  "m"  (*ptr),
    232                 [zero] "i"  (0)
    233               : "cr0", "ctr");
    234 
    235   return result;
    236 }
    237 
    238 #ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
    239 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
    240                                          Atomic64 old_value,
    241                                          Atomic64 new_value) {
    242   Atomic64 result;
    243 
    244   asm volatile (
    245       "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
    246       "       cmpd %[cmp], %[res]             \n\t"  // compare values
    247       "       bne- 2f                         \n\t"
    248 
    249       "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
    250       "       bne- 1b                         \n\t"
    251       "2:                                     \n\t"
    252               : [res]  "=&b" (result)
    253               : [obj]  "b"   (ptr),
    254                 [cmp]  "b"   (old_value),
    255                 [val]  "b"   (new_value),
    256                 [zero] "i"   (0)
    257               : "cr0", "ctr");
    258 
    259   return result;
    260 }
    261 
    262 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
    263                                          Atomic64 new_value) {
    264   Atomic64 result;
    265 
    266   asm volatile (
    267       "1:     ldarx %[res], %[zero], %[obj]       \n\t"
    268       "       stdcx. %[val], %[zero], %[obj]      \n\t"
    269       "       bne- 1b                             \n\t"
    270               : [res]  "=&b" (result)
    271               : [obj]  "b"   (ptr),
    272                 [val]  "b"   (new_value),
    273                 [zero] "i"   (0)
    274               : "cr0", "ctr");
    275 
    276   return result;
    277 }
    278 
    279 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
    280                                           Atomic64 increment) {
    281   Atomic64 result;
    282 
    283   asm volatile (
    284       "1:     ldarx %[res], %[zero], %[obj]   \n\t" // load and reserve
    285       "       add %[res], %[res], %[val]      \n\t" // add the operand
    286       "       stdcx. %[res], %[zero], %[obj]  \n\t" // store old value if
    287                                                     // still reserved
    288 
    289       "       bne- 1b                         \n\t"
    290               : [res]  "=&b" (result)
    291               : [obj]  "b"   (ptr),
    292                 [val]  "b"   (increment),
    293                 [zero] "i"   (0)
    294               : "cr0", "ctr");
    295 
    296   return result;
    297 }
    298 
    299 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
    300                                         Atomic64 increment) {
    301 
    302   Atomic64 result;
    303 
    304   asm volatile (
    305       "       lwsync                          \n\t"
    306 
    307       "1:     ldarx %[res], %[zero], %[obj]   \n\t" // load and reserve
    308       "       add %[res], %[res], %[val]      \n\t" // add the operand
    309       "       stdcx. %[res], %[zero], %[obj]  \n\t" // store old value if
    310                                                     // still reserved
    311 
    312       "       bne- 1b                         \n\t"
    313 
    314       "       isync                           \n\t"
    315               : [res]  "=&b" (result)
    316               : [obj]  "b"   (ptr),
    317                 [val]  "b"   (increment),
    318                 [zero] "i"   (0)
    319               : "cr0", "ctr");
    320 
    321   return result;
    322 }
    323 
    324 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
    325                                        Atomic64 old_value,
    326                                        Atomic64 new_value) {
    327   Atomic64 result;
    328 
    329   asm volatile (
    330       "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
    331       "       cmpd %[cmp], %[res]             \n\t"  // compare values
    332       "       bne- 2f                         \n\t"
    333 
    334       "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
    335       "       bne- 1b                         \n\t"
    336       "       isync                           \n\t"
    337       "2:                                     \n\t"
    338               : [res]  "=&b" (result)
    339               : [obj]  "b"   (ptr),
    340                 [cmp]  "b"   (old_value),
    341                 [val]  "b"   (new_value),
    342                 [zero] "i"   (0)
    343               : "cr0", "ctr");
    344 
    345   return result;
    346 }
    347 
    348 inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
    349                                        Atomic64 old_value,
    350                                        Atomic64 new_value) {
    351   Atomic64 result;
    352 
    353   asm volatile (
    354       "       lwsync                          \n\t"
    355 
    356       "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
    357       "       cmpd %[cmp], %[res]             \n\t"  // compare values
    358       "       bne- 2f                         \n\t"
    359 
    360       "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
    361       "       bne- 1b                         \n\t"
    362       "2:                                     \n\t"
    363               : [res]  "=&b" (result)
    364               : [obj]  "b"   (ptr),
    365                 [cmp]  "b"   (old_value),
    366                 [val]  "b"   (new_value),
    367                 [zero] "i"   (0)
    368               : "cr0", "ctr");
    369 
    370   return result;
    371 }
    372 
    373 inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
    374   *ptr = value;
    375 }
    376 
    377 inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
    378   asm volatile (
    379       "       std %[val], %[obj]          \n\t"
    380       "       isync                       \n\t"
    381               : [obj] "=m" (*ptr)
    382               : [val] "b"  (value));
    383 }
    384 
    385 inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
    386   asm volatile (
    387       "       lwsync                      \n\t"
    388       "       std %[val], %[obj]          \n\t"
    389               : [obj] "=m" (*ptr)
    390               : [val] "b"  (value));
    391 }
    392 
    393 inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
    394   return *ptr;
    395 }
    396 
    397 inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
    398   Atomic64 result;
    399 
    400   asm volatile (
    401       "1:     ld %[res], %[obj]                   \n\t"
    402       "       cmpd %[res], %[res]                 \n\t" // create data
    403                                                         // dependency for
    404                                                         // load/load ordering
    405       "       bne- 1b                             \n\t" // never taken
    406 
    407       "       isync                               \n\t"
    408               : [res]  "=b" (result)
    409               : [obj]  "m"  (*ptr),
    410                 [zero] "i"  (0)
    411               : "cr0", "ctr");
    412 
    413   return result;
    414 }
    415 
    416 inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
    417   Atomic64 result;
    418 
    419   asm volatile (
    420       "       lwsync                              \n\t"
    421 
    422       "1:     ld %[res], %[obj]                   \n\t"
    423       "       cmpd %[res], %[res]                 \n\t" // create data
    424                                                         // dependency for
    425                                                         // load/load ordering
    426       "       bne- 1b                             \n\t" // never taken
    427               : [res]  "=b" (result)
    428               : [obj]  "m"  (*ptr),
    429                 [zero] "i"  (0)
    430               : "cr0", "ctr");
    431 
    432   return result;
    433 }
    434 #endif
    435 
    436 }  // namespace internal
    437 }  // namespace protobuf
    438 }  // namespace google
    439 
    440 #endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
    441