1 /* 2 * Copyright (c) 1999, 2017, 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_VM_ATOMIC_SOLARIS_X86_HPP 26 #define OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP 27 28 inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } 29 inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } 30 inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } 31 32 33 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } 34 inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } 35 36 inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } 37 inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } 38 inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } 39 inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } 40 inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } 41 42 inline void Atomic::inc (volatile jint* dest) { (void)add (1, dest); } 43 inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); } 44 inline void Atomic::inc_ptr(volatile void* dest) { (void)add_ptr(1, dest); } 45 46 inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); } 47 inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); } 48 inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); } 49 50 // For Sun Studio - implementation is in solaris_x86_64.il. 51 52 extern "C" { 53 jint _Atomic_add(jint add_value, volatile jint* dest); 54 jlong _Atomic_add_long(jlong add_value, volatile jlong* dest); 55 56 jint _Atomic_xchg(jint exchange_value, volatile jint* dest); 57 jbyte _Atomic_cmpxchg_byte(jbyte exchange_value, volatile jbyte* dest, 58 jbyte compare_value); 59 jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest, 60 jint compare_value); 61 jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, 62 jlong compare_value); 63 } 64 65 template<size_t byte_size> 66 struct Atomic::PlatformAdd 67 : Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> > 68 { 69 template<typename I, typename D> 70 D add_and_fetch(I add_value, D volatile* dest) const; 71 }; 72 73 // Not using add_using_helper; see comment for cmpxchg. 74 template<> 75 template<typename I, typename D> 76 inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { 77 STATIC_ASSERT(4 == sizeof(I)); 78 STATIC_ASSERT(4 == sizeof(D)); 79 return PrimitiveConversions::cast<D>( 80 _Atomic_add(PrimitiveConversions::cast<jint>(add_value), 81 reinterpret_cast<jint volatile*>(dest))); 82 } 83 84 // Not using add_using_helper; see comment for cmpxchg. 85 template<> 86 template<typename I, typename D> 87 inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { 88 STATIC_ASSERT(8 == sizeof(I)); 89 STATIC_ASSERT(8 == sizeof(D)); 90 return PrimitiveConversions::cast<D>( 91 _Atomic_add_long(PrimitiveConversions::cast<jlong>(add_value), 92 reinterpret_cast<jlong volatile*>(dest))); 93 } 94 95 inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { 96 return _Atomic_xchg(exchange_value, 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 exchange_value, 108 T volatile* dest, 109 T compare_value, 110 cmpxchg_memory_order order) const { 111 STATIC_ASSERT(1 == sizeof(T)); 112 return PrimitiveConversions::cast<T>( 113 _Atomic_cmpxchg_byte(PrimitiveConversions::cast<jbyte>(exchange_value), 114 reinterpret_cast<jbyte volatile*>(dest), 115 PrimitiveConversions::cast<jbyte>(compare_value))); 116 } 117 118 template<> 119 template<typename T> 120 inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, 121 T volatile* dest, 122 T compare_value, 123 cmpxchg_memory_order order) const { 124 STATIC_ASSERT(4 == sizeof(T)); 125 return PrimitiveConversions::cast<T>( 126 _Atomic_cmpxchg(PrimitiveConversions::cast<jint>(exchange_value), 127 reinterpret_cast<jint volatile*>(dest), 128 PrimitiveConversions::cast<jint>(compare_value))); 129 } 130 131 template<> 132 template<typename T> 133 inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, 134 T volatile* dest, 135 T compare_value, 136 cmpxchg_memory_order order) const { 137 STATIC_ASSERT(8 == sizeof(T)); 138 return PrimitiveConversions::cast<T>( 139 _Atomic_cmpxchg_long(PrimitiveConversions::cast<jlong>(exchange_value), 140 reinterpret_cast<jlong volatile*>(dest), 141 PrimitiveConversions::cast<jlong>(compare_value))); 142 } 143 144 inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } 145 inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } 146 extern "C" jlong _Atomic_xchg_long(jlong exchange_value, volatile jlong* dest); 147 148 inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { 149 return (intptr_t)_Atomic_xchg_long((jlong)exchange_value, (volatile jlong*)dest); 150 } 151 152 inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { 153 return (void*)_Atomic_xchg_long((jlong)exchange_value, (volatile jlong*)dest); 154 } 155 156 inline jlong Atomic::load(const volatile jlong* src) { return *src; } 157 158 #endif // OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP