Here’s a code snippet from OpenJDK6’s hotspot/src/share/vm/prims/unsafe.cpp (starting on line 1082):
// JSR166 ------------------------------------------------------------------
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h);
oop e = JNIHandles::resolve(e_h);
oop p = JNIHandles::resolve(obj);
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
if (UseCompressedOops) {
update_barrier_set_pre((narrowOop*)addr, e);
} else {
update_barrier_set_pre((oop*)addr, e);
}
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
jboolean success = (res == e);
if (success)
update_barrier_set((void*)addr, x);
return success;
UNSAFE_END
The key method oopDesc::atomic_compare_exchange_oop is added also.
inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
volatile HeapWord *dest,
oop compare_value) {
if (UseCompressedOops) {
// encode exchange and compare value from oop to T
narrowOop val = encode_heap_oop(exchange_value);
narrowOop cmp = encode_heap_oop(compare_value);
narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp);
// decode old from T to oop
return decode_heap_oop(old);
} else {
return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);
}
}
What is the purpose of this code in the context of the JVM? I’m not experienced in C++.
Atomic::cmpxchg & Atomic::cmpxchg_ptr becomes OS & CPU & 32bit/64bit dependent. So JVMs are splitted here.
EDIT
As steve-O pointed out, CAS has its weakness as ABA problem, so memory barrier is necessary here to ensure the CAS is still correct in multithread environment. Also as CAS would need three paramter the address,old value and new value,so modern CPU is required for this process.
EDIT
With the new C++0x standard (not formal published now?) , does it mean that JVM don’t need to be spliited then? At least, in the source code level. The binary could be still splitted but it will be handled by the C++ compiler.
It is a JNI wrapper for the CAS API, with memory barriers for IA64 architecture.
edit: for a description of CAS:
Compare dest with compare value and if they match assign exchange value to dest.
It is an atomic operation which means no other processor can change the value of dest whilst the operation executes.
Typical problems that can occur without atomic operations are listed here, the “ABA problem”
http://en.wikipedia.org/wiki/ABA_problem
Why would you use a CAS function?
Easy example is a counter, if you have multiple threads incrementing a counter consider what the increment process does:
What happens when another processor reads the value of i and saves i + 1 before this processor has completed?
You end up with i + 1 instead of i + 2.