首页 > 其他 > 详细

jvm源码解读--16 cas 用法解析

时间:2021-05-19 16:27:12      阅读:15      评论:0      收藏:0      [点我收藏+]
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;

分析,有三个值,内存值V,旧的预期值A,新的修改值B;

如果A==V,那么把B赋值给V,返回V,如果A!=V,直接返回V;

 

进入

jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
  assert(sizeof(jbyte) == 1, "assumption.");
  uintptr_t dest_addr = (uintptr_t)dest;
  uintptr_t offset = dest_addr % sizeof(jint);
  volatile jint* dest_int = (volatile jint*)(dest_addr - offset);
  jint cur = *dest_int;
  jbyte* cur_as_bytes = (jbyte*)(&cur);
  jint new_val = cur;
  jbyte* new_val_as_bytes = (jbyte*)(&new_val);
  new_val_as_bytes[offset] = exchange_value;
  while (cur_as_bytes[offset] == compare_value) {
    jint res = cmpxchg(new_val, dest_int, cur);// 
if (res == cur) break; cur = res; new_val = cur; new_val_as_bytes[offset] = exchange_value; } return cur_as_bytes[offset]; }

inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {

                    // 

return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP());
}

 
                        // 
inline jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp) {
#ifdef AMD64 __asm__ __volatile__ (LOCK_IF_MP(
%4) "cmpxchgq %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory"); return exchange_value; #else return _Atomic_cmpxchg_long_gcc(exchange_value, dest, compare_value, os::is_MP()); #if 0 // The code below does not work presumably because of the bug in gcc // The error message says: // can‘t find a register in class BREG while reloading asm // However I want to save this code and later replace _Atomic_cmpxchg_long_gcc // with such inline asm code: volatile jlong_accessor evl, cvl, rv; evl.long_value = exchange_value; cvl.long_value = compare_value; int mp = os::is_MP(); __asm__ volatile ("cmp $0, %%esi\n\t" "je 1f \n\t" "lock\n\t" "1: cmpxchg8b (%%edi)\n\t" : "=a"(cvl.words[0]), "=d"(cvl.words[1]) : "a"(cvl.words[0]), "d"(cvl.words[1]), "b"(evl.words[0]), "c"(evl.words[1]), "D"(dest), "S"(mp) : "cc", "memory"); return cvl.long_value; #endif // if 0 #endif // AMD64 }

技术分享图片

jvm源码解读--16 cas 用法解析

原文:https://www.cnblogs.com/zytcomeon/p/14784900.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!