compareAndSwapInt实现

compareAndSwapInt

unsafe.compareAndSwapInt(this, valueOffset, expect, update)

接口定义

public final native boolean compareAndSwapInt(Object object, long offset, int expect, int update);

CMPXCHG

CMPXCHG—Compare and Exchange

lock cmpxchg 指令

unsafe.cpp

Unsafe_CompareAndSwapInt

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); //把jobject转化成oop
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;  // compare_val 比较eax的值
UNSAFE_END

index_oop_from_field_offset_long

/** //计算变量的内存绝对地址 */
inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
  jlong byte_offset = field_offset_to_byte_offset(field_offset);
#ifdef ASSERT
    jlong p_size = HeapWordSize * (jlong)(p->size());
    assert(byte_offset < p_size, err_msg("Unsafe access: offset " INT64_FORMAT " > object's size " INT64_FORMAT, byte_offset, p_size));
  }
#endif
  if (sizeof(char*) == sizeof(jint))    // (this constant folds!)
    return (address)p + (jint) byte_offset;
  else
    return (address)p +        byte_offset;
}

LOCK_IF_MP

#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "

jniHandles.hpp

# 把jobject转化成oop
inline oop JNIHandles::resolve(jobject handle) {
  oop result = (handle == NULL ? (oop)NULL : *(oop*)handle);
  assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle");
  assert(result != badJNIHandle, "Pointing to zapped jni handle area");
  return result;
};

atomic_linux_x86.inline.hpp

Atomic::cmpxchg

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  int mp = os::is_MP();
  __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" // 汇编语句
                    : "=a" (exchange_value) // 输出寄存器
                    : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) // 输入寄存器
                    : "cc", "memory"); //会被修改的寄存器
  return exchange_value; // %0 = exchange_value %1=exchange_value  %2=compare_value  %3=dest  %4=mp
} // 从输出寄存器序列从左到右从上到下以%0开始

// cmpxchgl末尾l表示操作数长度为4字节

这里是引用

atomic_windows_x86.inline.hpp

Atomic::cmpxchg

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest    
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

cmpxchgl %1,(%3)实际上表示cmpxchgl exchange_value,(dest), 此处(dest)表示dest地址所存的值

cmpxchgl有个隐含操作数eax,其实际过程是先比较eax的值(也就是compare_value)和dest地址所存的值是否相等

如果相等则把exchange_value的值写入dest指向的地址

如果不相等则把dest地址所存的值存入eax中

输出是"=a" (exchange_value),表示把eax中存的值写入exchange_value变量中

​​​
在这里插入图片描述

os.hpp

# 判断当前环境是否为多处理器环境
static inline bool is_MP() {
    // During bootstrap if _processor_count is not yet initialized
    // we claim to be MP as that is safest. If any platform has a
    // stub generator that might be triggered in this phase and for
    // which being declared MP when in fact not, is a problem - then
    // the bootstrap routine for the stub generator needs to check
    // the processor count directly and leave the bootstrap routine
    // in place until called after initialization has ocurred.
    return (_processor_count != 1) || AssumeMP;
  }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值