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 : Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> > 46 { 47 template<typename D, typename I> 48 D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const; 49 }; 50 51 // Not using add_using_helper; see comment for cmpxchg. 52 template<> 53 template<typename D, typename I> 54 inline D Atomic::PlatformAdd<4>::add_and_fetch(D volatile* dest, I add_value, 55 atomic_memory_order order) const { 56 STATIC_ASSERT(4 == sizeof(I)); 57 STATIC_ASSERT(4 == sizeof(D)); 58 return PrimitiveConversions::cast<D>( 59 _Atomic_add(PrimitiveConversions::cast<int32_t>(add_value), 60 reinterpret_cast<int32_t volatile*>(dest))); 61 } 62 63 // Not using add_using_helper; see comment for cmpxchg. 64 template<> 65 template<typename D, typename I> 66 inline D Atomic::PlatformAdd<8>::add_and_fetch(D volatile* dest, I add_value, 67 atomic_memory_order order) const { 68 STATIC_ASSERT(8 == sizeof(I)); 69 STATIC_ASSERT(8 == sizeof(D)); 70 return PrimitiveConversions::cast<D>( 71 _Atomic_add_long(PrimitiveConversions::cast<int64_t>(add_value), 72 reinterpret_cast<int64_t volatile*>(dest))); 73 } 74 75 template<> 76 template<typename T> 77 inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, 78 T exchange_value, 79 atomic_memory_order order) const { 80 STATIC_ASSERT(4 == sizeof(T)); 81 return PrimitiveConversions::cast<T>( 82 _Atomic_xchg(PrimitiveConversions::cast<int32_t>(exchange_value), 83 reinterpret_cast<int32_t volatile*>(dest))); 84 } 85 86 extern "C" int64_t _Atomic_xchg_long(int64_t exchange_value, volatile int64_t* dest); 87 88 template<> 89 template<typename T> 90 inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, 91 T exchange_value, 92 atomic_memory_order order) const { 93 STATIC_ASSERT(8 == sizeof(T)); 94 return PrimitiveConversions::cast<T>( 95 _Atomic_xchg_long(PrimitiveConversions::cast<int64_t>(exchange_value), 96 reinterpret_cast<int64_t volatile*>(dest))); 97 } 98 99 // Not using cmpxchg_using_helper here, because some configurations of 100 // Solaris compiler don't deal well with passing a "defined in .il" 101 // function as an argument. We *should* switch to using gcc-style 102 // inline assembly, but attempting to do so with Studio 12.4 ran into 103 // segfaults. 104 105 template<> 106 template<typename T> 107 inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, 108 T compare_value, 109 T exchange_value, 110 atomic_memory_order order) const { 111 STATIC_ASSERT(1 == sizeof(T)); 112 return PrimitiveConversions::cast<T>( 113 _Atomic_cmpxchg_byte(PrimitiveConversions::cast<int8_t>(exchange_value), 114 reinterpret_cast<int8_t volatile*>(dest), 115 PrimitiveConversions::cast<int8_t>(compare_value))); 116 } 117 118 template<> 119 template<typename T> 120 inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, 121 T compare_value, 122 T exchange_value, 123 atomic_memory_order order) const { 124 STATIC_ASSERT(4 == sizeof(T)); 125 return PrimitiveConversions::cast<T>( 126 _Atomic_cmpxchg(PrimitiveConversions::cast<int32_t>(exchange_value), 127 reinterpret_cast<int32_t volatile*>(dest), 128 PrimitiveConversions::cast<int32_t>(compare_value))); 129 } 130 131 template<> 132 template<typename T> 133 inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, 134 T compare_value, 135 T exchange_value, 136 atomic_memory_order order) const { 137 STATIC_ASSERT(8 == sizeof(T)); 138 return PrimitiveConversions::cast<T>( 139 _Atomic_cmpxchg_long(PrimitiveConversions::cast<int64_t>(exchange_value), 140 reinterpret_cast<int64_t volatile*>(dest), 141 PrimitiveConversions::cast<int64_t>(compare_value))); 142 } 143 144 #endif // OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP