260 } |
260 } |
261 OrderAccess::fence(); |
261 OrderAccess::fence(); |
262 UNSAFE_END |
262 UNSAFE_END |
263 |
263 |
264 #ifndef SUPPORTS_NATIVE_CX8 |
264 #ifndef SUPPORTS_NATIVE_CX8 |
265 // Keep old code for platforms which may not have atomic jlong (8 bytes) instructions |
265 |
266 |
266 // VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'. |
267 // Volatile long versions must use locks if !VM_Version::supports_cx8(). |
267 // |
268 // support_cx8 is a surrogate for 'supports atomic long memory ops'. |
268 // On platforms which do not support atomic compare-and-swap of jlong (8 byte) |
|
269 // values we have to use a lock-based scheme to enforce atomicity. This has to be |
|
270 // applied to all Unsafe operations that set the value of a jlong field. Even so |
|
271 // the compareAndSwapLong operation will not be atomic with respect to direct stores |
|
272 // to the field from Java code. It is important therefore that any Java code that |
|
273 // utilizes these Unsafe jlong operations does not perform direct stores. To permit |
|
274 // direct loads of the field from Java code we must also use Atomic::store within the |
|
275 // locked regions. And for good measure, in case there are direct stores, we also |
|
276 // employ Atomic::load within those regions. Note that the field in question must be |
|
277 // volatile and so must have atomic load/store accesses applied at the Java level. |
|
278 // |
|
279 // The locking scheme could utilize a range of strategies for controlling the locking |
|
280 // granularity: from a lock per-field through to a single global lock. The latter is |
|
281 // the simplest and is used for the current implementation. Note that the Java object |
|
282 // that contains the field, can not, in general, be used for locking. To do so can lead |
|
283 // to deadlocks as we may introduce locking into what appears to the Java code to be a |
|
284 // lock-free path. |
|
285 // |
|
286 // As all the locked-regions are very short and themselves non-blocking we can treat |
|
287 // them as leaf routines and elide safepoint checks (ie we don't perform any thread |
|
288 // state transitions even when blocking for the lock). Note that if we do choose to |
|
289 // add safepoint checks and thread state transitions, we must ensure that we calculate |
|
290 // the address of the field _after_ we have acquired the lock, else the object may have |
|
291 // been moved by the GC |
269 |
292 |
270 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) |
293 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) |
271 UnsafeWrapper("Unsafe_GetLongVolatile"); |
294 UnsafeWrapper("Unsafe_GetLongVolatile"); |
272 { |
295 { |
273 if (VM_Version::supports_cx8()) { |
296 if (VM_Version::supports_cx8()) { |
291 SET_FIELD_VOLATILE(obj, offset, jlong, x); |
314 SET_FIELD_VOLATILE(obj, offset, jlong, x); |
292 } |
315 } |
293 else { |
316 else { |
294 Handle p (THREAD, JNIHandles::resolve(obj)); |
317 Handle p (THREAD, JNIHandles::resolve(obj)); |
295 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); |
318 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); |
296 ObjectLocker ol(p, THREAD); |
319 MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); |
297 *addr = x; |
320 Atomic::store(x, addr); |
298 } |
321 } |
299 } |
322 } |
300 UNSAFE_END |
323 UNSAFE_END |
301 |
324 |
302 #endif // not SUPPORTS_NATIVE_CX8 |
325 #endif // not SUPPORTS_NATIVE_CX8 |
401 SET_FIELD_VOLATILE(obj, offset, jlong, x); |
424 SET_FIELD_VOLATILE(obj, offset, jlong, x); |
402 } |
425 } |
403 else { |
426 else { |
404 Handle p (THREAD, JNIHandles::resolve(obj)); |
427 Handle p (THREAD, JNIHandles::resolve(obj)); |
405 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); |
428 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); |
406 ObjectLocker ol(p, THREAD); |
429 MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); |
407 *addr = x; |
430 Atomic::store(x, addr); |
408 } |
431 } |
409 } |
432 } |
410 #endif |
433 #endif |
411 UNSAFE_END |
434 UNSAFE_END |
412 |
435 |
1150 |
1173 |
1151 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) |
1174 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) |
1152 UnsafeWrapper("Unsafe_CompareAndSwapLong"); |
1175 UnsafeWrapper("Unsafe_CompareAndSwapLong"); |
1153 Handle p (THREAD, JNIHandles::resolve(obj)); |
1176 Handle p (THREAD, JNIHandles::resolve(obj)); |
1154 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); |
1177 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); |
|
1178 #ifdef SUPPORTS_NATIVE_CX8 |
|
1179 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; |
|
1180 #else |
1155 if (VM_Version::supports_cx8()) |
1181 if (VM_Version::supports_cx8()) |
1156 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; |
1182 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; |
1157 else { |
1183 else { |
1158 jboolean success = false; |
1184 jboolean success = false; |
1159 ObjectLocker ol(p, THREAD); |
1185 MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); |
1160 if (*addr == e) { *addr = x; success = true; } |
1186 jlong val = Atomic::load(addr); |
|
1187 if (val == e) { Atomic::store(x, addr); success = true; } |
1161 return success; |
1188 return success; |
1162 } |
1189 } |
|
1190 #endif |
1163 UNSAFE_END |
1191 UNSAFE_END |
1164 |
1192 |
1165 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) |
1193 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) |
1166 UnsafeWrapper("Unsafe_Park"); |
1194 UnsafeWrapper("Unsafe_Park"); |
1167 EventThreadPark event; |
1195 EventThreadPark event; |