| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Copyright 2013 Red Hat Inc. All rights reserved. |
| 2 // Copyright 2012 Google Inc. All rights reserved. | |
| 3 // http://code.google.com/p/protobuf/ | |
| 4 // | 2 // |
| 5 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 7 // met: | 5 // met: |
| 8 // | 6 // |
| 9 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 11 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 12 // copyright notice, this list of conditions and the following disclaimer | 10 // copyright notice, this list of conditions and the following disclaimer |
| 13 // in the documentation and/or other materials provided with the | 11 // in the documentation and/or other materials provided with the |
| 14 // distribution. | 12 // distribution. |
| 15 // * Neither the name of Google Inc. nor the names of its | 13 // * Neither the name of Red Hat Inc. nor the names of its |
| 16 // contributors may be used to endorse or promote products derived from | 14 // contributors may be used to endorse or promote products derived from |
| 17 // this software without specific prior written permission. | 15 // this software without specific prior written permission. |
| 18 // | 16 // |
| 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 28 |
| 31 // This file is an internal atomic implementation, use atomicops.h instead. | 29 // This file is an internal atomic implementation, use atomicops.h instead. |
| 32 | 30 |
| 33 #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ | 31 #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ |
| 34 #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ | 32 #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ |
| 35 | |
| 36 // For _smp_cmpxchg() | |
| 37 #include <pthread.h> | |
| 38 | 33 |
| 39 namespace google { | 34 namespace google { |
| 40 namespace protobuf { | 35 namespace protobuf { |
| 41 namespace internal { | 36 namespace internal { |
| 42 | 37 |
| 43 inline Atomic32 QNXCmpxchg(Atomic32 old_value, | |
| 44 Atomic32 new_value, | |
| 45 volatile Atomic32* ptr) { | |
| 46 return static_cast<Atomic32>( | |
| 47 _smp_cmpxchg((volatile unsigned *)ptr, | |
| 48 (unsigned)old_value, | |
| 49 (unsigned)new_value)); | |
| 50 } | |
| 51 | |
| 52 | |
| 53 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, | 38 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, |
| 54 Atomic32 old_value, | 39 Atomic32 old_value, |
| 55 Atomic32 new_value) { | 40 Atomic32 new_value) { |
| 56 Atomic32 prev_value = *ptr; | 41 __atomic_compare_exchange_n(ptr, &old_value, new_value, true, |
| 57 do { | 42 __ATOMIC_RELAXED, __ATOMIC_RELAXED); |
| 58 if (!QNXCmpxchg(old_value, new_value, | 43 return old_value; |
| 59 const_cast<Atomic32*>(ptr))) { | |
| 60 return old_value; | |
| 61 } | |
| 62 prev_value = *ptr; | |
| 63 } while (prev_value == old_value); | |
| 64 return prev_value; | |
| 65 } | 44 } |
| 66 | 45 |
| 67 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, | 46 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, |
| 68 Atomic32 new_value) { | 47 Atomic32 new_value) { |
| 69 Atomic32 old_value; | 48 return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); |
| 70 do { | |
| 71 old_value = *ptr; | |
| 72 } while (QNXCmpxchg(old_value, new_value, | |
| 73 const_cast<Atomic32*>(ptr))); | |
| 74 return old_value; | |
| 75 } | 49 } |
| 76 | 50 |
| 77 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, | 51 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, |
| 78 Atomic32 increment) { | 52 Atomic32 increment) { |
| 79 return Barrier_AtomicIncrement(ptr, increment); | 53 return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED); |
| 80 } | 54 } |
| 81 | 55 |
| 82 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, | 56 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, |
| 83 Atomic32 increment) { | 57 Atomic32 increment) { |
| 84 for (;;) { | 58 return __atomic_add_fetch(ptr, increment, __ATOMIC_SEQ_CST); |
| 85 // Atomic exchange the old value with an incremented one. | |
| 86 Atomic32 old_value = *ptr; | |
| 87 Atomic32 new_value = old_value + increment; | |
| 88 if (QNXCmpxchg(old_value, new_value, | |
| 89 const_cast<Atomic32*>(ptr)) == 0) { | |
| 90 // The exchange took place as expected. | |
| 91 return new_value; | |
| 92 } | |
| 93 // Otherwise, *ptr changed mid-loop and we need to retry. | |
| 94 } | |
| 95 } | 59 } |
| 96 | 60 |
| 97 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, | 61 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, |
| 98 Atomic32 old_value, | 62 Atomic32 old_value, |
| 99 Atomic32 new_value) { | 63 Atomic32 new_value) { |
| 100 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); | 64 __atomic_compare_exchange_n(ptr, &old_value, new_value, true, |
| 65 __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); |
| 66 return old_value; |
| 101 } | 67 } |
| 102 | 68 |
| 103 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, | 69 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, |
| 104 Atomic32 old_value, | 70 Atomic32 old_value, |
| 105 Atomic32 new_value) { | 71 Atomic32 new_value) { |
| 106 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); | 72 __atomic_compare_exchange_n(ptr, &old_value, new_value, true, |
| 73 __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); |
| 74 return old_value; |
| 107 } | 75 } |
| 108 | 76 |
| 109 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { | 77 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { |
| 110 *ptr = value; | 78 __atomic_store_n(ptr, value, __ATOMIC_RELAXED); |
| 111 } | 79 } |
| 112 | 80 |
| 113 inline void MemoryBarrier() { | 81 inline void MemoryBarrier() { |
| 114 __sync_synchronize(); | 82 __sync_synchronize(); |
| 115 } | 83 } |
| 116 | 84 |
| 117 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { | 85 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { |
| 118 *ptr = value; | 86 __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST); |
| 119 MemoryBarrier(); | |
| 120 } | 87 } |
| 121 | 88 |
| 122 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { | 89 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { |
| 123 MemoryBarrier(); | 90 __atomic_store_n(ptr, value, __ATOMIC_RELEASE); |
| 124 *ptr = value; | |
| 125 } | 91 } |
| 126 | 92 |
| 127 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { | 93 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { |
| 128 return *ptr; | 94 return __atomic_load_n(ptr, __ATOMIC_RELAXED); |
| 129 } | 95 } |
| 130 | 96 |
| 131 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { | 97 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { |
| 132 Atomic32 value = *ptr; | 98 return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); |
| 133 MemoryBarrier(); | |
| 134 return value; | |
| 135 } | 99 } |
| 136 | 100 |
| 137 inline Atomic32 Release_Load(volatile const Atomic32* ptr) { | 101 inline Atomic32 Release_Load(volatile const Atomic32* ptr) { |
| 138 MemoryBarrier(); | 102 return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); |
| 139 return *ptr; | |
| 140 } | 103 } |
| 141 | 104 |
| 105 #ifdef __LP64__ |
| 106 |
| 107 inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { |
| 108 __atomic_store_n(ptr, value, __ATOMIC_RELEASE); |
| 109 } |
| 110 |
| 111 inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { |
| 112 return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); |
| 113 } |
| 114 |
| 115 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, |
| 116 Atomic64 old_value, |
| 117 Atomic64 new_value) { |
| 118 __atomic_compare_exchange_n(ptr, &old_value, new_value, true, |
| 119 __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); |
| 120 return old_value; |
| 121 } |
| 122 |
| 123 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, |
| 124 Atomic64 old_value, |
| 125 Atomic64 new_value) { |
| 126 __atomic_compare_exchange_n(ptr, &old_value, new_value, true, |
| 127 __ATOMIC_RELAXED, __ATOMIC_RELAXED); |
| 128 return old_value; |
| 129 } |
| 130 |
| 131 #endif // defined(__LP64__) |
| 132 |
| 142 } // namespace internal | 133 } // namespace internal |
| 143 } // namespace protobuf | 134 } // namespace protobuf |
| 144 } // namespace google | 135 } // namespace google |
| 145 | 136 |
| 146 #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ | 137 #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ |
| OLD | NEW |