1 /* 2 * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP 26 #define OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP 27 28 // For Sun Studio - implementation is in solaris_x86_64.il. 29 30 extern "C" { 31 int32_t _Atomic_add(int32_t add_value, volatile int32_t* dest); 32 int64_t _Atomic_add_long(int64_t add_value, volatile int64_t* dest); 33 34 int32_t _Atomic_xchg(int32_t exchange_value, volatile int32_t* dest); 35 int8_t _Atomic_cmpxchg_byte(int8_t exchange_value, volatile int8_t* dest, 36 int8_t compare_value); 37 int32_t _Atomic_cmpxchg(int32_t exchange_value, volatile int32_t* dest, 38 int32_t compare_value); 39 int64_t _Atomic_cmpxchg_long(int64_t exchange_value, volatile int64_t* dest, 40 int64_t compare_value); 41 } 42 43 template<size_t byte_size> 44 struct Atomic::PlatformAdd { 45 template<typename D, typename I> 46 D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const; 47 48 template<typename D, typename I> 49 D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const { 50 return add_and_fetch(dest, add_value, order) - add_value; 51 } 52 }; 53 54 // Not using add_using_helper; see comment for cmpxchg. 55 template<> 56 template<typename D, typename I> 57 inline D Atomic::PlatformAdd<4>::add_and_fetch(D volatile* dest, I add_value, 58 atomic_memory_order order) const { 59 STATIC_ASSERT(4 == sizeof(I)); 60 STATIC_ASSERT(4 == sizeof(D)); 61 return PrimitiveConversions::cast<D>( 62 _Atomic_add(PrimitiveConversions::cast<int32_t>(add_value), 63 reinterpret_cast<int32_t volatile*>(dest))); 64 } 65 66 // Not using add_using_helper; see comment for cmpxchg. 67 template<> 68 template<typename D, typename I> 69 inline D Atomic::PlatformAdd<8>::add_and_fetch(D volatile* dest, I add_value, 70 atomic_memory_order order) const { 71 STATIC_ASSERT(8 == sizeof(I)); 72 STATIC_ASSERT(8 == sizeof(D)); 73 return PrimitiveConversions::cast<D>( 74 _Atomic_add_long(PrimitiveConversions::cast<int64_t>(add_value), 75 reinterpret_cast<int64_t volatile*>(dest))); 76 } 77 78 template<> 79 template<typename T> 80 inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, 81 T exchange_value, 82 atomic_memory_order order) const { 83 STATIC_ASSERT(4 == sizeof(T)); 84 return PrimitiveConversions::cast<T>( 85 _Atomic_xchg(PrimitiveConversions::cast<int32_t>(exchange_value), 86 reinterpret_cast<int32_t volatile*>(dest))); 87 } 88 89 extern "C" int64_t _Atomic_xchg_long(int64_t exchange_value, volatile int64_t* dest); 90 91 template<> 92 template<typename T> 93 inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, 94 T exchange_value, 95 atomic_memory_order order) const { 96 STATIC_ASSERT(8 == sizeof(T)); 97 return PrimitiveConversions::cast<T>( 98 _Atomic_xchg_long(PrimitiveConversions::cast<int64_t>(exchange_value), 99 reinterpret_cast<int64_t volatile*>(dest))); 100 } 101 102 // Not using cmpxchg_using_helper here, because some configurations of 103 // Solaris compiler don't deal well with passing a "defined in .il" 104 // function as an argument. We *should* switch to using gcc-style 105 // inline assembly, but attempting to do so with Studio 12.4 ran into 106 // segfaults. 107 108 template<> 109 template<typename T> 110 inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, 111 T compare_value, 112 T exchange_value, 113 atomic_memory_order order) const { 114 STATIC_ASSERT(1 == sizeof(T)); 115 return PrimitiveConversions::cast<T>( 116 _Atomic_cmpxchg_byte(PrimitiveConversions::cast<int8_t>(exchange_value), 117 reinterpret_cast<int8_t volatile*>(dest), 118 PrimitiveConversions::cast<int8_t>(compare_value))); 119 } 120 121 template<> 122 template<typename T> 123 inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, 124 T compare_value, 125 T exchange_value, 126 atomic_memory_order order) const { 127 STATIC_ASSERT(4 == sizeof(T)); 128 return PrimitiveConversions::cast<T>( 129 _Atomic_cmpxchg(PrimitiveConversions::cast<int32_t>(exchange_value), 130 reinterpret_cast<int32_t volatile*>(dest), 131 PrimitiveConversions::cast<int32_t>(compare_value))); 132 } 133 134 template<> 135 template<typename T> 136 inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, 137 T compare_value, 138 T exchange_value, 139 atomic_memory_order order) const { 140 STATIC_ASSERT(8 == sizeof(T)); 141 return PrimitiveConversions::cast<T>( 142 _Atomic_cmpxchg_long(PrimitiveConversions::cast<int64_t>(exchange_value), 143 reinterpret_cast<int64_t volatile*>(dest), 144 PrimitiveConversions::cast<int64_t>(compare_value))); 145 } 146 147 #endif // OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP