1.1 --- a/src/share/vm/prims/unsafe.cpp Wed Dec 17 10:43:38 2014 -0800 1.2 +++ b/src/share/vm/prims/unsafe.cpp Tue Nov 25 21:00:21 2014 -0500 1.3 @@ -322,10 +322,33 @@ 1.4 UNSAFE_END 1.5 1.6 #ifndef SUPPORTS_NATIVE_CX8 1.7 -// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions 1.8 1.9 -// Volatile long versions must use locks if !VM_Version::supports_cx8(). 1.10 -// support_cx8 is a surrogate for 'supports atomic long memory ops'. 1.11 +// VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'. 1.12 +// 1.13 +// On platforms which do not support atomic compare-and-swap of jlong (8 byte) 1.14 +// values we have to use a lock-based scheme to enforce atomicity. This has to be 1.15 +// applied to all Unsafe operations that set the value of a jlong field. Even so 1.16 +// the compareAndSwapLong operation will not be atomic with respect to direct stores 1.17 +// to the field from Java code. It is important therefore that any Java code that 1.18 +// utilizes these Unsafe jlong operations does not perform direct stores. To permit 1.19 +// direct loads of the field from Java code we must also use Atomic::store within the 1.20 +// locked regions. And for good measure, in case there are direct stores, we also 1.21 +// employ Atomic::load within those regions. Note that the field in question must be 1.22 +// volatile and so must have atomic load/store accesses applied at the Java level. 1.23 +// 1.24 +// The locking scheme could utilize a range of strategies for controlling the locking 1.25 +// granularity: from a lock per-field through to a single global lock. The latter is 1.26 +// the simplest and is used for the current implementation. Note that the Java object 1.27 +// that contains the field, can not, in general, be used for locking. To do so can lead 1.28 +// to deadlocks as we may introduce locking into what appears to the Java code to be a 1.29 +// lock-free path. 1.30 +// 1.31 +// As all the locked-regions are very short and themselves non-blocking we can treat 1.32 +// them as leaf routines and elide safepoint checks (ie we don't perform any thread 1.33 +// state transitions even when blocking for the lock). Note that if we do choose to 1.34 +// add safepoint checks and thread state transitions, we must ensure that we calculate 1.35 +// the address of the field _after_ we have acquired the lock, else the object may have 1.36 +// been moved by the GC 1.37 1.38 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) 1.39 UnsafeWrapper("Unsafe_GetLongVolatile"); 1.40 @@ -337,8 +360,8 @@ 1.41 else { 1.42 Handle p (THREAD, JNIHandles::resolve(obj)); 1.43 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); 1.44 - ObjectLocker ol(p, THREAD); 1.45 - jlong value = *addr; 1.46 + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); 1.47 + jlong value = Atomic::load(addr); 1.48 return value; 1.49 } 1.50 } 1.51 @@ -353,8 +376,8 @@ 1.52 else { 1.53 Handle p (THREAD, JNIHandles::resolve(obj)); 1.54 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); 1.55 - ObjectLocker ol(p, THREAD); 1.56 - *addr = x; 1.57 + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); 1.58 + Atomic::store(x, addr); 1.59 } 1.60 } 1.61 UNSAFE_END 1.62 @@ -463,8 +486,8 @@ 1.63 else { 1.64 Handle p (THREAD, JNIHandles::resolve(obj)); 1.65 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); 1.66 - ObjectLocker ol(p, THREAD); 1.67 - *addr = x; 1.68 + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); 1.69 + Atomic::store(x, addr); 1.70 } 1.71 } 1.72 #endif 1.73 @@ -1213,14 +1236,19 @@ 1.74 UnsafeWrapper("Unsafe_CompareAndSwapLong"); 1.75 Handle p (THREAD, JNIHandles::resolve(obj)); 1.76 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); 1.77 +#ifdef SUPPORTS_NATIVE_CX8 1.78 + return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; 1.79 +#else 1.80 if (VM_Version::supports_cx8()) 1.81 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; 1.82 else { 1.83 jboolean success = false; 1.84 - ObjectLocker ol(p, THREAD); 1.85 - if (*addr == e) { *addr = x; success = true; } 1.86 + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); 1.87 + jlong val = Atomic::load(addr); 1.88 + if (val == e) { Atomic::store(x, addr); success = true; } 1.89 return success; 1.90 } 1.91 +#endif 1.92 UNSAFE_END 1.93 1.94 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))