1 /*
2  * Copyright (c) 1999, 2018, 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 // 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 I, typename D>
48   D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const;
49 };
50 
51 // Not using add_using_helper; see comment for cmpxchg.
52 template<>
53 template<typename I, typename D>
add_and_fetch(I add_value,D volatile * dest,atomic_memory_order order) const54 inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest,
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 I, typename D>
add_and_fetch(I add_value,D volatile * dest,atomic_memory_order order) const66 inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest,
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>
operator ()(T exchange_value,T volatile * dest,atomic_memory_order order) const77 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value,
78                                              T volatile* dest,
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>
operator ()(T exchange_value,T volatile * dest,atomic_memory_order order) const90 inline T Atomic::PlatformXchg<8>::operator()(T exchange_value,
91                                              T volatile* dest,
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>
operator ()(T exchange_value,T volatile * dest,T compare_value,atomic_memory_order order) const107 inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value,
108                                                 T volatile* dest,
109                                                 T compare_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>
operator ()(T exchange_value,T volatile * dest,T compare_value,atomic_memory_order order) const120 inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
121                                                 T volatile* dest,
122                                                 T compare_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>
operator ()(T exchange_value,T volatile * dest,T compare_value,atomic_memory_order order) const133 inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
134                                                 T volatile* dest,
135                                                 T compare_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_VM_ATOMIC_SOLARIS_X86_HPP
145