# HG changeset patch # User mdoerr # Date 1461243757 -7200 # Node ID acb5f3825543f24c2a551f7eb2788c17fa083614 # Parent 72bd11005099a936dbbdcb06ce81672406ec5952 8154736: enhancement of cmpxchg and copy_to_survivor for ppc64 Reviewed-by: Contributed-by: HORII@jp.ibm.com, mdoerr diff --git a/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp b/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp --- a/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp +++ b/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp @@ -291,8 +291,36 @@ return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); } +inline void cmpxchg_pre_membar(memory_order order) { + if (order == memory_order_seq_cst) { + __asm__ __volatile__ ( + /* fence */ + strasm_sync + ); + } else if (order == memory_order_release || order == memory_order_acq_rel) { + __asm__ __volatile__ ( + /* release */ + strasm_lwsync + ); + } +} + +inline void cmpxchg_post_membar(memory_order order) { + if (order == memory_order_seq_cst) { + __asm__ __volatile__ ( + /* fence */ + strasm_sync + ); + } else if (order == memory_order_acquire || order == memory_order_acq_rel) { + __asm__ __volatile__ ( + /* acquire */ + strasm_isync + ); + } +} + #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { // Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' @@ -312,9 +340,9 @@ unsigned int old_value, value32; + cmpxchg_pre_membar(order); + __asm__ __volatile__ ( - /* fence */ - strasm_sync /* simple guard */ " lbz %[old_value], 0(%[dest]) \n" " cmpw %[masked_compare_val], %[old_value] \n" @@ -331,8 +359,6 @@ " xor %[value32], %[xor_value], %[value32] \n" " stwcx. %[value32], 0, %[dest_base] \n" " bne- 1b \n" - /* acquire */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -353,10 +379,12 @@ "memory" ); + cmpxchg_post_membar(order); + return (jbyte)(unsigned char)old_value; } -inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { // Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' @@ -365,9 +393,9 @@ unsigned int old_value; const uint64_t zero = 0; + cmpxchg_pre_membar(order); + __asm__ __volatile__ ( - /* fence */ - strasm_sync /* simple guard */ " lwz %[old_value], 0(%[dest]) \n" " cmpw %[compare_value], %[old_value] \n" @@ -379,8 +407,6 @@ " bne- 2f \n" " stwcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* acquire */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -397,10 +423,12 @@ "memory" ); + cmpxchg_post_membar(order); + return (jint) old_value; } -inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { // Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' @@ -409,9 +437,9 @@ long old_value; const uint64_t zero = 0; + cmpxchg_pre_membar(order); + __asm__ __volatile__ ( - /* fence */ - strasm_sync /* simple guard */ " ld %[old_value], 0(%[dest]) \n" " cmpd %[compare_value], %[old_value] \n" @@ -423,8 +451,6 @@ " bne- 2f \n" " stdcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* acquire */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -441,15 +467,17 @@ "memory" ); + cmpxchg_post_membar(order); + return (jlong) old_value; } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } #undef strasm_sync diff --git a/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp b/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp --- a/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp +++ b/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp @@ -89,7 +89,7 @@ } #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgb %1,(%3)" : "=a" (exchange_value) @@ -98,7 +98,7 @@ return exchange_value; } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" : "=a" (exchange_value) @@ -149,7 +149,7 @@ return exchange_value; } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { bool mp = os::is_MP(); __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" : "=a" (exchange_value) @@ -158,12 +158,12 @@ return exchange_value; } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { return *src; } @@ -197,16 +197,16 @@ void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP()); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { diff --git a/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp --- a/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp +++ b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp @@ -270,7 +270,7 @@ inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, - jint compare_value) { + jint compare_value, memory_order order) { #ifdef ARM return arm_compare_and_swap(dest, compare_value, exchange_value); #else @@ -284,14 +284,14 @@ inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, - jlong compare_value) { + jlong compare_value, memory_order order) { return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, - intptr_t compare_value) { + intptr_t compare_value, memory_order order) { #ifdef ARM return arm_compare_and_swap(dest, compare_value, exchange_value); #else @@ -305,7 +305,7 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, - void* compare_value) { + void* compare_value, memory_order order) { return (void *) cmpxchg_ptr((intptr_t) exchange_value, (volatile intptr_t*) dest, diff --git a/src/os_cpu/linux_aarch64/vm/atomic_linux_aarch64.inline.hpp b/src/os_cpu/linux_aarch64/vm/atomic_linux_aarch64.inline.hpp --- a/src/os_cpu/linux_aarch64/vm/atomic_linux_aarch64.inline.hpp +++ b/src/os_cpu/linux_aarch64/vm/atomic_linux_aarch64.inline.hpp @@ -88,7 +88,7 @@ } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } @@ -123,21 +123,21 @@ return res; } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { return (void *) cmpxchg_ptr((intptr_t) exchange_value, (volatile intptr_t*) dest, - (intptr_t) compare_value); + (intptr_t) compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { return *src; } diff --git a/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp b/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp --- a/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp +++ b/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp @@ -291,8 +291,36 @@ return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); } +inline void cmpxchg_pre_membar(memory_order order) { + if (order == memory_order_seq_cst) { + __asm__ __volatile__ ( + /* fence */ + strasm_sync + ); + } else if (order == memory_order_release || order == memory_order_acq_rel) { + __asm__ __volatile__ ( + /* release */ + strasm_lwsync + ); + } +} + +inline void cmpxchg_post_membar(memory_order order) { + if (order == memory_order_seq_cst) { + __asm__ __volatile__ ( + /* fence */ + strasm_sync + ); + } else if (order == memory_order_acquire || order == memory_order_acq_rel) { + __asm__ __volatile__ ( + /* acquire */ + strasm_isync + ); + } +} + #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { // Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' @@ -312,9 +340,9 @@ unsigned int old_value, value32; + cmpxchg_pre_membar(order); + __asm__ __volatile__ ( - /* fence */ - strasm_sync /* simple guard */ " lbz %[old_value], 0(%[dest]) \n" " cmpw %[masked_compare_val], %[old_value] \n" @@ -331,8 +359,6 @@ " xor %[value32], %[xor_value], %[value32] \n" " stwcx. %[value32], 0, %[dest_base] \n" " bne- 1b \n" - /* acquire */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -353,10 +379,12 @@ "memory" ); + cmpxchg_post_membar(order); + return (jbyte)(unsigned char)old_value; } -inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { // Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' @@ -365,9 +393,9 @@ unsigned int old_value; const uint64_t zero = 0; + cmpxchg_pre_membar(order); + __asm__ __volatile__ ( - /* fence */ - strasm_sync /* simple guard */ " lwz %[old_value], 0(%[dest]) \n" " cmpw %[compare_value], %[old_value] \n" @@ -379,8 +407,6 @@ " bne- 2f \n" " stwcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* acquire */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -397,10 +423,12 @@ "memory" ); + cmpxchg_post_membar(order); + return (jint) old_value; } -inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { // Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' @@ -409,9 +437,9 @@ long old_value; const uint64_t zero = 0; + cmpxchg_pre_membar(order); + __asm__ __volatile__ ( - /* fence */ - strasm_sync /* simple guard */ " ld %[old_value], 0(%[dest]) \n" " cmpd %[compare_value], %[old_value] \n" @@ -423,8 +451,6 @@ " bne- 2f \n" " stdcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* acquire */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -441,15 +467,17 @@ "memory" ); + cmpxchg_post_membar(order); + return (jlong) old_value; } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } #undef strasm_sync diff --git a/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp b/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp --- a/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp +++ b/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp @@ -148,7 +148,7 @@ } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { jint rv; __asm__ volatile( " cas [%2], %3, %0" @@ -158,7 +158,7 @@ return rv; } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { #ifdef _LP64 jlong rv; __asm__ volatile( @@ -190,7 +190,7 @@ #endif } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { intptr_t rv; #ifdef _LP64 __asm__ volatile( @@ -208,8 +208,8 @@ return rv; } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value, order); } #endif // OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP diff --git a/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp b/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp --- a/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp +++ b/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp @@ -89,7 +89,7 @@ } #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgb %1,(%3)" : "=a" (exchange_value) @@ -98,7 +98,7 @@ return exchange_value; } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" : "=a" (exchange_value) @@ -149,7 +149,7 @@ return exchange_value; } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { bool mp = os::is_MP(); __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" : "=a" (exchange_value) @@ -158,12 +158,12 @@ return exchange_value; } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { return *src; } @@ -197,16 +197,16 @@ void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP()); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { diff --git a/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp b/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp --- a/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp +++ b/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp @@ -264,7 +264,7 @@ inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, - jint compare_value) { + jint compare_value, memory_order order) { #ifdef ARM return arm_compare_and_swap(dest, compare_value, exchange_value); #else @@ -278,14 +278,14 @@ inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, - jlong compare_value) { + jlong compare_value, memory_order order) { return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, - intptr_t compare_value) { + intptr_t compare_value, memory_order order) { #ifdef ARM return arm_compare_and_swap(dest, compare_value, exchange_value); #else @@ -299,11 +299,11 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, - void* compare_value) { + void* compare_value, memory_order order) { return (void *) cmpxchg_ptr((intptr_t) exchange_value, (volatile intptr_t*) dest, - (intptr_t) compare_value); + (intptr_t) compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { diff --git a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp --- a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp +++ b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp @@ -177,7 +177,7 @@ } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { jint rv; __asm__ volatile( " cas [%2], %3, %0" @@ -187,7 +187,7 @@ return rv; } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { #ifdef _LP64 jlong rv; __asm__ volatile( @@ -219,7 +219,7 @@ #endif //_LP64 } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { intptr_t rv; #ifdef _LP64 __asm__ volatile( @@ -237,8 +237,8 @@ return rv; } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value, order); } #else // _GNU_SOURCE @@ -296,11 +296,11 @@ } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { return _Atomic_cas32(exchange_value, dest, compare_value); } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { #ifdef _LP64 // Return 64 bit value in %o0 return _Atomic_cas64((intptr_t)exchange_value, (intptr_t *)dest, (intptr_t)compare_value); @@ -310,7 +310,7 @@ #endif // _LP64 } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { #ifdef _LP64 return _Atomic_cas64(exchange_value, dest, compare_value); #else // _LP64 @@ -318,8 +318,8 @@ #endif // _LP64 } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value, order); } @@ -354,20 +354,20 @@ } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { return (*os::atomic_cmpxchg_func)(exchange_value, dest, compare_value); } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { return (*os::atomic_cmpxchg_long_func)(exchange_value, dest, compare_value); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } #endif // _LP64 || COMPILER2 diff --git a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp --- a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp +++ b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp @@ -85,15 +85,15 @@ } #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { return _Atomic_cmpxchg_byte(exchange_value, dest, compare_value IS_MP_ARG()); } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { return _Atomic_cmpxchg(exchange_value, dest, compare_value IS_MP_ARG()); } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { return _Atomic_cmpxchg_long(exchange_value, dest, compare_value IS_MP_ARG()); } @@ -120,12 +120,12 @@ return (void*)_Atomic_xchg_long((jlong)exchange_value, (volatile jlong*)dest); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { return *src; } @@ -148,12 +148,12 @@ return (void*)xchg((jint)exchange_value, (volatile jint*)dest); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } extern "C" void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); diff --git a/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp b/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp --- a/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp +++ b/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp @@ -119,25 +119,25 @@ return (void *)(os::atomic_xchg_ptr_func)((intptr_t)exchange_value, (volatile intptr_t*)dest); } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { return (*os::atomic_cmpxchg_func)(exchange_value, dest, compare_value); } #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { return (*os::atomic_cmpxchg_byte_func)(exchange_value, dest, compare_value); } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { return (*os::atomic_cmpxchg_long_func)(exchange_value, dest, compare_value); } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { return *src; } @@ -218,7 +218,7 @@ } #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE -inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { +inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order) { // alternative for InterlockedCompareExchange int mp = os::is_MP(); __asm { @@ -230,7 +230,7 @@ } } -inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order) { // alternative for InterlockedCompareExchange int mp = os::is_MP(); __asm { @@ -242,7 +242,7 @@ } } -inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order) { int mp = os::is_MP(); jint ex_lo = (jint)exchange_value; jint ex_hi = *( ((jint*)&exchange_value) + 1 ); @@ -263,12 +263,12 @@ } } -inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { - return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } -inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { - return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value, order); } inline jlong Atomic::load(volatile jlong* src) { diff --git a/src/share/vm/gc/parallel/psPromotionManager.cpp b/src/share/vm/gc/parallel/psPromotionManager.cpp --- a/src/share/vm/gc/parallel/psPromotionManager.cpp +++ b/src/share/vm/gc/parallel/psPromotionManager.cpp @@ -439,7 +439,7 @@ // this started. If it is the same (i.e., no forwarding // pointer has been installed), then this thread owns // it. - if (obj->cas_forward_to(obj, obj_mark)) { + if (obj->cas_forward_to(obj, obj_mark, memory_order_relaxed)) { // We won any races, we "own" this object. assert(obj == obj->forwardee(), "Sanity"); diff --git a/src/share/vm/gc/parallel/psPromotionManager.inline.hpp b/src/share/vm/gc/parallel/psPromotionManager.inline.hpp --- a/src/share/vm/gc/parallel/psPromotionManager.inline.hpp +++ b/src/share/vm/gc/parallel/psPromotionManager.inline.hpp @@ -211,7 +211,7 @@ Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)new_obj, new_obj_size); // Now we have to CAS in the header. - if (o->cas_forward_to(new_obj, test_mark)) { + if (o->cas_forward_to(new_obj, test_mark, memory_order_relaxed)) { // We won any races, we "own" this object. assert(new_obj == o->forwardee(), "Sanity"); diff --git a/src/share/vm/oops/oop.hpp b/src/share/vm/oops/oop.hpp --- a/src/share/vm/oops/oop.hpp +++ b/src/share/vm/oops/oop.hpp @@ -30,6 +30,7 @@ #include "memory/memRegion.hpp" #include "oops/metadata.hpp" #include "utilities/macros.hpp" +#include "runtime/atomic.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe // the format of Java objects so the fields can be accessed from C++. @@ -75,7 +76,7 @@ void set_mark(volatile markOop m) { _mark = m; } inline void release_set_mark(markOop m); - inline markOop cas_set_mark(markOop new_mark, markOop old_mark); + inline markOop cas_set_mark(markOop new_mark, markOop old_mark, memory_order order = memory_order_seq_cst); // Used only to re-initialize the mark word (e.g., of promoted // objects during a GC) -- requires a valid klass pointer @@ -298,7 +299,7 @@ inline bool is_forwarded() const; inline void forward_to(oop p); - inline bool cas_forward_to(oop p, markOop compare); + inline bool cas_forward_to(oop p, markOop compare, memory_order order = memory_order_seq_cst); #if INCLUDE_ALL_GCS // Like "forward_to", but inserts the forwarding pointer atomically. diff --git a/src/share/vm/oops/oop.inline.hpp b/src/share/vm/oops/oop.inline.hpp --- a/src/share/vm/oops/oop.inline.hpp +++ b/src/share/vm/oops/oop.inline.hpp @@ -92,8 +92,8 @@ OrderAccess::release_store_ptr(&_mark, m); } -markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark) { - return (markOop) Atomic::cmpxchg_ptr(new_mark, &_mark, old_mark); +markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark, memory_order order) { + return (markOop) Atomic::cmpxchg_ptr(new_mark, &_mark, old_mark, order); } void oopDesc::init_mark() { @@ -578,14 +578,14 @@ } // Used by parallel scavengers -bool oopDesc::cas_forward_to(oop p, markOop compare) { +bool oopDesc::cas_forward_to(oop p, markOop compare, memory_order order) { assert(check_obj_alignment(p), "forwarding to something not aligned"); assert(Universe::heap()->is_in_reserved(p), "forwarding to something not in heap"); markOop m = markOopDesc::encode_pointer_as_mark(p); assert(m->decode_pointer() == p, "encoding must be reversable"); - return cas_set_mark(m, compare) == compare; + return cas_set_mark(m, compare, order) == compare; } #if INCLUDE_ALL_GCS diff --git a/src/share/vm/runtime/atomic.cpp b/src/share/vm/runtime/atomic.cpp --- a/src/share/vm/runtime/atomic.cpp +++ b/src/share/vm/runtime/atomic.cpp @@ -57,10 +57,11 @@ } unsigned Atomic::cmpxchg(unsigned int exchange_value, - volatile unsigned int* dest, unsigned int compare_value) { + volatile unsigned int* dest, unsigned int compare_value, + memory_order order) { assert(sizeof(unsigned int) == sizeof(jint), "more work to do"); return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest, - (jint)compare_value); + (jint)compare_value, order); } jlong Atomic::add(jlong add_value, volatile jlong* dest) { diff --git a/src/share/vm/runtime/atomic.hpp b/src/share/vm/runtime/atomic.hpp --- a/src/share/vm/runtime/atomic.hpp +++ b/src/share/vm/runtime/atomic.hpp @@ -27,6 +27,15 @@ #include "memory/allocation.hpp" +typedef enum memory_order { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} memory_order; + class Atomic : AllStatic { private: static jbyte cmpxchg_general(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value); @@ -107,13 +116,13 @@ // *dest with exchange_value if the comparison succeeded. Returns prior // value of *dest. cmpxchg*() provide: // compare-and-exchange - inline static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value); - inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value); + inline static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, memory_order order = memory_order_seq_cst); + inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, memory_order order = memory_order_seq_cst); // See comment above about using jlong atomics on 32-bit platforms - inline static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value); - static unsigned int cmpxchg (unsigned int exchange_value, volatile unsigned int* dest, unsigned int compare_value); - inline static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value); - inline static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value); + inline static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, memory_order order = memory_order_seq_cst); + static unsigned int cmpxchg (unsigned int exchange_value, volatile unsigned int* dest, unsigned int compare_value, memory_order order = memory_order_seq_cst); + inline static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, memory_order order = memory_order_seq_cst); + inline static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, memory_order order = memory_order_seq_cst); }; // To use Atomic::inc(jshort* dest) and Atomic::dec(jshort* dest), the address must be specially