hotspot/src/share/vm/prims/unsafe.cpp
changeset 27874 e9b44eb1613f
parent 27471 6e56277909f1
child 27880 afb974a04396
equal deleted inserted replaced
27873:60cce297ef8e 27874:e9b44eb1613f
   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()) {
   275       return v;
   298       return v;
   276     }
   299     }
   277     else {
   300     else {
   278       Handle p (THREAD, JNIHandles::resolve(obj));
   301       Handle p (THREAD, JNIHandles::resolve(obj));
   279       jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
   302       jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
   280       ObjectLocker ol(p, THREAD);
   303       MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
   281       jlong value = *addr;
   304       jlong value = Atomic::load(addr);
   282       return value;
   305       return value;
   283     }
   306     }
   284   }
   307   }
   285 UNSAFE_END
   308 UNSAFE_END
   286 
   309 
   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;