atomic_bsd_x86.hpp revision 13477:4d61110c6046
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_BSD_X86_VM_ATOMIC_BSD_X86_HPP
26#define OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_HPP
27
28// Implementation of class atomic
29
30inline void Atomic::store    (jbyte    store_value, jbyte*    dest) { *dest = store_value; }
31inline void Atomic::store    (jshort   store_value, jshort*   dest) { *dest = store_value; }
32inline void Atomic::store    (jint     store_value, jint*     dest) { *dest = store_value; }
33inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
34inline void Atomic::store_ptr(void*    store_value, void*     dest) { *(void**)dest = store_value; }
35
36inline void Atomic::store    (jbyte    store_value, volatile jbyte*    dest) { *dest = store_value; }
37inline void Atomic::store    (jshort   store_value, volatile jshort*   dest) { *dest = store_value; }
38inline void Atomic::store    (jint     store_value, volatile jint*     dest) { *dest = store_value; }
39inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
40inline void Atomic::store_ptr(void*    store_value, volatile void*     dest) { *(void* volatile *)dest = store_value; }
41
42
43inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
44  jint addend = add_value;
45  __asm__ volatile (  "lock xaddl %0,(%2)"
46                    : "=r" (addend)
47                    : "0" (addend), "r" (dest)
48                    : "cc", "memory");
49  return addend + add_value;
50}
51
52inline void Atomic::inc    (volatile jint*     dest) {
53  __asm__ volatile (  "lock addl $1,(%0)" :
54                    : "r" (dest) : "cc", "memory");
55}
56
57inline void Atomic::inc_ptr(volatile void*     dest) {
58  inc_ptr((volatile intptr_t*)dest);
59}
60
61inline void Atomic::dec    (volatile jint*     dest) {
62  __asm__ volatile (  "lock subl $1,(%0)" :
63                    : "r" (dest) : "cc", "memory");
64}
65
66inline void Atomic::dec_ptr(volatile void*     dest) {
67  dec_ptr((volatile intptr_t*)dest);
68}
69
70inline jint     Atomic::xchg    (jint     exchange_value, volatile jint*     dest) {
71  __asm__ volatile (  "xchgl (%2),%0"
72                    : "=r" (exchange_value)
73                    : "0" (exchange_value), "r" (dest)
74                    : "memory");
75  return exchange_value;
76}
77
78inline void*    Atomic::xchg_ptr(void*    exchange_value, volatile void*     dest) {
79  return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
80}
81
82template<>
83template<typename T>
84inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value,
85                                                T volatile* dest,
86                                                T compare_value,
87                                                cmpxchg_memory_order /* order */) const {
88  STATIC_ASSERT(1 == sizeof(T));
89  __asm__ volatile (  "lock cmpxchgb %1,(%3)"
90                    : "=a" (exchange_value)
91                    : "q" (exchange_value), "a" (compare_value), "r" (dest)
92                    : "cc", "memory");
93  return exchange_value;
94}
95
96template<>
97template<typename T>
98inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
99                                                T volatile* dest,
100                                                T compare_value,
101                                                cmpxchg_memory_order /* order */) const {
102  STATIC_ASSERT(4 == sizeof(T));
103  __asm__ volatile (  "lock cmpxchgl %1,(%3)"
104                    : "=a" (exchange_value)
105                    : "r" (exchange_value), "a" (compare_value), "r" (dest)
106                    : "cc", "memory");
107  return exchange_value;
108}
109
110#ifdef AMD64
111inline void Atomic::store    (jlong    store_value, jlong*    dest) { *dest = store_value; }
112inline void Atomic::store    (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
113
114inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
115  intptr_t addend = add_value;
116  __asm__ __volatile__ (  "lock xaddq %0,(%2)"
117                        : "=r" (addend)
118                        : "0" (addend), "r" (dest)
119                        : "cc", "memory");
120  return addend + add_value;
121}
122
123inline void*    Atomic::add_ptr(intptr_t add_value, volatile void*     dest) {
124  return (void*)add_ptr(add_value, (volatile intptr_t*)dest);
125}
126
127inline void Atomic::inc_ptr(volatile intptr_t* dest) {
128  __asm__ __volatile__ (  "lock addq $1,(%0)"
129                        :
130                        : "r" (dest)
131                        : "cc", "memory");
132}
133
134inline void Atomic::dec_ptr(volatile intptr_t* dest) {
135  __asm__ __volatile__ (  "lock subq $1,(%0)"
136                        :
137                        : "r" (dest)
138                        : "cc", "memory");
139}
140
141inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
142  __asm__ __volatile__ ("xchgq (%2),%0"
143                        : "=r" (exchange_value)
144                        : "0" (exchange_value), "r" (dest)
145                        : "memory");
146  return exchange_value;
147}
148
149template<>
150template<typename T>
151inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
152                                                T volatile* dest,
153                                                T compare_value,
154                                                cmpxchg_memory_order /* order */) const {
155  STATIC_ASSERT(8 == sizeof(T));
156  __asm__ __volatile__ (  "lock cmpxchgq %1,(%3)"
157                        : "=a" (exchange_value)
158                        : "r" (exchange_value), "a" (compare_value), "r" (dest)
159                        : "cc", "memory");
160  return exchange_value;
161}
162
163inline jlong Atomic::load(const volatile jlong* src) { return *src; }
164
165#else // !AMD64
166
167inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
168  return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest);
169}
170
171inline void*    Atomic::add_ptr(intptr_t add_value, volatile void*     dest) {
172  return (void*)Atomic::add((jint)add_value, (volatile jint*)dest);
173}
174
175
176inline void Atomic::inc_ptr(volatile intptr_t* dest) {
177  inc((volatile jint*)dest);
178}
179
180inline void Atomic::dec_ptr(volatile intptr_t* dest) {
181  dec((volatile jint*)dest);
182}
183
184inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
185  return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
186}
187
188extern "C" {
189  // defined in bsd_x86.s
190  jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
191  void _Atomic_move_long(const volatile jlong* src, volatile jlong* dst);
192}
193
194template<>
195template<typename T>
196inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
197                                                T volatile* dest,
198                                                T compare_value,
199                                                cmpxchg_memory_order order) const {
200  STATIC_ASSERT(8 == sizeof(T));
201  return cmpxchg_using_helper<jlong>(_Atomic_cmpxchg_long, exchange_value, dest, compare_value);
202}
203
204inline jlong Atomic::load(const volatile jlong* src) {
205  volatile jlong dest;
206  _Atomic_move_long(src, &dest);
207  return dest;
208}
209
210inline void Atomic::store(jlong store_value, jlong* dest) {
211  _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
212}
213
214inline void Atomic::store(jlong store_value, volatile jlong* dest) {
215  _Atomic_move_long((volatile jlong*)&store_value, dest);
216}
217
218#endif // AMD64
219
220#endif // OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_HPP
221