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;
}