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_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_HPP 26 #define OS_CPU_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_HPP 27 28 #include "runtime/os.hpp" 29 30 // The following alternative implementations are needed because 31 // Windows 95 doesn't support (some of) the corresponding Windows NT 32 // calls. Furthermore, these versions allow inlining in the caller. 33 // (More precisely: The documentation for InterlockedExchange says 34 // it is supported for Windows 95. However, when single-stepping 35 // through the assembly code we cannot step into the routine and 36 // when looking at the routine address we see only garbage code. 37 // Better safe then sorry!). Was bug 7/31/98 (gri). 38 // 39 // Performance note: On uniprocessors, the 'lock' prefixes are not 40 // necessary (and expensive). We should generate separate cases if 41 // this becomes a performance problem. 42 43 #pragma warning(disable: 4035) // Disables warnings reporting missing return statement 44 45 #ifdef AMD64 46 47 template <> 48 inline int32_t Atomic::specialized_add<int32_t>(int32_t add_value, volatile int32_t* dest) { 49 return (int32_t)(*os::atomic_add_func)(add_value, dest); 50 } 51 52 template <> 53 inline int64_t Atomic::specialized_add<int64_t>(int64_t add_value, volatile int64_t* dest) { 54 return (intptr_t)(*os::atomic_add_ptr_func)(add_value, dest); 55 } 56 57 template <> 58 inline int32_t Atomic::specialized_xchg<int32_t>(int32_t exchange_value, volatile int32_t* dest) { 59 return (int32_t)(*os::atomic_xchg_func)(exchange_value, dest); 60 } 61 62 template <> 63 inline int64_t Atomic::specialized_xchg<int64_t>(int64_t exchange_value, volatile int64_t* dest) { 64 return (intptr_t)(os::atomic_xchg_ptr_func)(exchange_value, dest); 65 } 66 67 template <> 68 inline int32_t Atomic::specialized_cmpxchg<int32_t>(int32_t exchange_value, volatile int32_t* dest, int32_t compare_value, cmpxchg_memory_order order) { 69 return (*os::atomic_cmpxchg_func)(exchange_value, dest, compare_value); 70 } 71 72 #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE 73 template <> 74 inline int8_t Atomic::specialized_cmpxchg<int8_t>(int8_t exchange_value, volatile int8_t* dest, int8_t compare_value, cmpxchg_memory_order order) { 75 return (*os::atomic_cmpxchg_byte_func)(exchange_value, dest, compare_value); 76 } 77 78 template <> 79 inline int64_t Atomic::specialized_cmpxchg<int64_t>(int64_t exchange_value, volatile int64_t* dest, int64_t compare_value, cmpxchg_memory_order order) { 80 return (*os::atomic_cmpxchg_long_func)(exchange_value, dest, compare_value); 81 } 82 83 #else // !AMD64 84 85 template <> 86 inline int32_t Atomic::specialized_add<int32_t>(int32_t add_value, volatile int32_t* dest) { 87 __asm { 88 mov edx, dest; 89 mov eax, add_value; 90 mov ecx, eax; 91 lock xadd dword ptr [edx], eax; 92 add eax, ecx; 93 } 94 } 95 96 template <> 97 inline void Atomic::specialized_inc<int32_t>(volatile int32_t* dest) { 98 // alternative for InterlockedIncrement 99 __asm { 100 mov edx, dest; 101 lock add dword ptr [edx], 1; 102 } 103 } 104 105 template <> 106 inline void Atomic::specialized_dec<int32_t>(volatile int32_t* dest) { 107 // alternative for InterlockedDecrement 108 __asm { 109 mov edx, dest; 110 lock sub dword ptr [edx], 1; 111 } 112 } 113 114 template <> 115 inline int32_t Atomic::specialized_xchg<int32_t>(int32_t exchange_value, volatile int32_t* dest) { 116 // alternative for InterlockedExchange 117 __asm { 118 mov eax, exchange_value; 119 mov ecx, dest; 120 xchg eax, dword ptr [ecx]; 121 } 122 } 123 124 #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE 125 template <> 126 inline int8_t Atomic::specialized_cmpxchg<int8_t>(int8_t exchange_value, volatile int8_t* dest, int8_t compare_value, cmpxchg_memory_order order) { 127 // alternative for InterlockedCompareExchange 128 __asm { 129 mov edx, dest 130 mov cl, exchange_value 131 mov al, compare_value 132 lock cmpxchg byte ptr [edx], cl 133 } 134 } 135 136 template <> 137 inline int32_t Atomic::specialized_cmpxchg<int32_t>(int32_t exchange_value, volatile int32_t* dest, int32_t compare_value, cmpxchg_memory_order order) { 138 // alternative for InterlockedCompareExchange 139 __asm { 140 mov edx, dest 141 mov ecx, exchange_value 142 mov eax, compare_value 143 lock cmpxchg dword ptr [edx], ecx 144 } 145 } 146 147 template <> 148 inline int64_t Atomic::specialized_cmpxchg<int64_t>(int64_t exchange_value, volatile int64_t* dest, int64_t compare_value, cmpxchg_memory_order order) { 149 int32_t ex_lo = (int32_t)exchange_value; 150 int32_t ex_hi = *( ((int32_t*)&exchange_value) + 1 ); 151 int32_t cmp_lo = (int32_t)compare_value; 152 int32_t cmp_hi = *( ((int32_t*)&compare_value) + 1 ); 153 __asm { 154 push ebx 155 push edi 156 mov eax, cmp_lo 157 mov edx, cmp_hi 158 mov edi, dest 159 mov ebx, ex_lo 160 mov ecx, ex_hi 161 lock cmpxchg8b qword ptr [edi] 162 pop edi 163 pop ebx 164 } 165 } 166 167 template <> 168 inline int64_t Atomic::specialized_load<int64_t>(const volatile int64_t* src) { 169 volatile int64_t dest; 170 volatile int64_t* pdest = &dest; 171 __asm { 172 mov eax, src 173 fild qword ptr [eax] 174 mov eax, pdest 175 fistp qword ptr [eax] 176 } 177 return dest; 178 } 179 180 template <> 181 inline void Atomic::specialized_store<int64_t>(int64_t store_value, volatile int64_t* dest) { 182 volatile int64_t* src = &store_value; 183 __asm { 184 mov eax, src 185 fild qword ptr [eax] 186 mov eax, dest 187 fistp qword ptr [eax] 188 } 189 } 190 191 #endif // AMD64 192 193 #pragma warning(default: 4035) // Enables warnings reporting missing return statement 194 195 #endif // OS_CPU_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_HPP