Skip to content

Commit f0f2e70

Browse files
zifeihanRealFYang
authored andcommitted
8326936: RISC-V: Shenandoah GC crashes due to incorrect atomic memory operations
8316186: RISC-V: Remove PlatformCmpxchg<4> 8330242: RISC-V: Simplify and remove CORRECT_COMPILER_ATOMIC_SUPPORT in atomic_linux_riscv.hpp Reviewed-by: fyang Backport-of: a089ed2b9289eeda73bba47ac87e5bc81a4af9dc
1 parent 7743b6c commit f0f2e70

File tree

1 file changed

+42
-37
lines changed

1 file changed

+42
-37
lines changed

src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
#if defined(__clang_major__)
3737
#define FULL_COMPILER_ATOMIC_SUPPORT
38-
#elif (__GNUC__ > 13) || ((__GNUC__ == 13) && (__GNUC_MINOR__ >= 2))
38+
#elif (__GNUC__ > 13) || ((__GNUC__ == 13) && (__GNUC_MINOR__ > 2))
3939
#define FULL_COMPILER_ATOMIC_SUPPORT
4040
#endif
4141

@@ -114,6 +114,44 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest __attribute__((
114114
}
115115
#endif
116116

117+
#ifndef FULL_COMPILER_ATOMIC_SUPPORT
118+
// The implementation of `__atomic_compare_exchange` lacks sign extensions
119+
// in GCC 13.2 and lower when using with 32-bit unsigned integers on RV64,
120+
// so we should implement it manually.
121+
// GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114130.
122+
// See also JDK-8326936.
123+
template<>
124+
template<typename T>
125+
inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__((unused)),
126+
T compare_value,
127+
T exchange_value,
128+
atomic_memory_order order) const {
129+
STATIC_ASSERT(4 == sizeof(T));
130+
131+
int32_t old_value;
132+
uint64_t rc_temp;
133+
134+
if (order != memory_order_relaxed) {
135+
FULL_MEM_BARRIER;
136+
}
137+
138+
__asm__ __volatile__ (
139+
"1: lr.w %0, %2 \n\t"
140+
" bne %0, %3, 2f \n\t"
141+
" sc.w %1, %4, %2 \n\t"
142+
" bnez %1, 1b \n\t"
143+
"2: \n\t"
144+
: /*%0*/"=&r" (old_value), /*%1*/"=&r" (rc_temp), /*%2*/"+A" (*dest)
145+
: /*%3*/"r" ((int64_t)(int32_t)compare_value), /*%4*/"r" (exchange_value)
146+
: "memory" );
147+
148+
if (order != memory_order_relaxed) {
149+
FULL_MEM_BARRIER;
150+
}
151+
return (T)old_value;
152+
}
153+
#endif
154+
117155
template<size_t byte_size>
118156
template<typename T>
119157
inline T Atomic::PlatformXchg<byte_size>::operator()(T volatile* dest,
@@ -148,54 +186,21 @@ inline T Atomic::PlatformCmpxchg<byte_size>::operator()(T volatile* dest __attri
148186
atomic_memory_order order) const {
149187

150188
#ifndef FULL_COMPILER_ATOMIC_SUPPORT
151-
STATIC_ASSERT(byte_size >= 4);
189+
STATIC_ASSERT(byte_size > 4);
152190
#endif
153191

154192
STATIC_ASSERT(byte_size == sizeof(T));
155-
T value = compare_value;
156193
if (order != memory_order_relaxed) {
157194
FULL_MEM_BARRIER;
158195
}
159196

160-
__atomic_compare_exchange(dest, &value, &exchange_value, /* weak */ false,
197+
__atomic_compare_exchange(dest, &compare_value, &exchange_value, /* weak */ false,
161198
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
162199

163200
if (order != memory_order_relaxed) {
164201
FULL_MEM_BARRIER;
165202
}
166-
return value;
167-
}
168-
169-
template<>
170-
template<typename T>
171-
inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__((unused)),
172-
T compare_value,
173-
T exchange_value,
174-
atomic_memory_order order) const {
175-
STATIC_ASSERT(4 == sizeof(T));
176-
177-
T old_value;
178-
long rc;
179-
180-
if (order != memory_order_relaxed) {
181-
FULL_MEM_BARRIER;
182-
}
183-
184-
__asm__ __volatile__ (
185-
"1: sext.w %1, %3 \n\t" // sign-extend compare_value
186-
" lr.w %0, %2 \n\t"
187-
" bne %0, %1, 2f \n\t"
188-
" sc.w %1, %4, %2 \n\t"
189-
" bnez %1, 1b \n\t"
190-
"2: \n\t"
191-
: /*%0*/"=&r" (old_value), /*%1*/"=&r" (rc), /*%2*/"+A" (*dest)
192-
: /*%3*/"r" (compare_value), /*%4*/"r" (exchange_value)
193-
: "memory" );
194-
195-
if (order != memory_order_relaxed) {
196-
FULL_MEM_BARRIER;
197-
}
198-
return old_value;
203+
return compare_value;
199204
}
200205

201206
template<size_t byte_size>

0 commit comments

Comments
 (0)