From 2ae0188a357f2f03f4624790c392660add896c83 Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Thu, 18 Apr 2024 01:26:00 +0000 Subject: [PATCH 1/3] 8330242: RISC-V: Simplify and remove CORRECT_COMPILER_ATOMIC_SUPPORT in atomic_linux_riscv.hpp Backport-of: cd4c3aac63ddab3d3618df09787d6e9311454ff8 --- .../os_cpu/linux_riscv/atomic_linux_riscv.hpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp index 6546adb6ff3..b3e35d6cc10 100644 --- a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp +++ b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp @@ -35,16 +35,10 @@ #if defined(__clang_major__) #define FULL_COMPILER_ATOMIC_SUPPORT -#elif (__GNUC__ > 13) || ((__GNUC__ == 13) && (__GNUC_MINOR__ >= 2)) +#elif (__GNUC__ > 13) || ((__GNUC__ == 13) && (__GNUC_MINOR__ > 2)) #define FULL_COMPILER_ATOMIC_SUPPORT #endif -#if defined(__clang_major__) -#define CORRECT_COMPILER_ATOMIC_SUPPORT -#elif defined(__GNUC__) && (__riscv_xlen <= 32 || __GNUC__ > 13) -#define CORRECT_COMPILER_ATOMIC_SUPPORT -#endif - template struct Atomic::PlatformAdd { template @@ -120,9 +114,9 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest __attribute__(( } #endif -#ifndef CORRECT_COMPILER_ATOMIC_SUPPORT +#ifndef FULL_COMPILER_ATOMIC_SUPPORT // The implementation of `__atomic_compare_exchange` lacks sign extensions -// in GCC 13 and lower when using with 32-bit unsigned integers on RV64, +// in GCC 13.2 and lower when using with 32-bit unsigned integers on RV64, // so we should implement it manually. // GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114130. // See also JDK-8326936. @@ -192,11 +186,7 @@ inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attri atomic_memory_order order) const { #ifndef FULL_COMPILER_ATOMIC_SUPPORT - STATIC_ASSERT(byte_size >= 4); -#endif - -#ifndef CORRECT_COMPILER_ATOMIC_SUPPORT - STATIC_ASSERT(byte_size != 4); + STATIC_ASSERT(byte_size > 4); #endif STATIC_ASSERT(byte_size == sizeof(T)); @@ -235,6 +225,5 @@ struct Atomic::PlatformOrderedStore }; #undef FULL_COMPILER_ATOMIC_SUPPORT -#undef CORRECT_COMPILER_ATOMIC_SUPPORT #endif // OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP From 0c572566963be7f941228deda2691ce2fc456c15 Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Thu, 18 Apr 2024 05:41:09 +0000 Subject: [PATCH 2/3] 8327990: [macosx-aarch64] Various tests fail with -XX:+AssertWXAtThreadSync Reviewed-by: phh Backport-of: e41bc42deb22615c9b93ee639d04e9ed2bd57f64 --- src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp | 2 ++ src/hotspot/share/jfr/jni/jfrJniMethod.cpp | 4 +++- src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp | 1 + src/hotspot/share/jfr/support/jfrIntrinsics.cpp | 1 + src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp | 1 + src/hotspot/share/prims/jvmtiExport.cpp | 1 + src/hotspot/share/prims/jvmtiExtensions.cpp | 1 + 7 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp b/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp index f2007231c22..882d468a4a3 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp @@ -156,6 +156,8 @@ void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, return; } ResourceMark rm(THREAD); + // WXWrite is needed before entering the vm below and in callee methods. + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, THREAD)); jclass* const classes = create_classes_array(classes_count, CHECK); assert(classes != nullptr, "invariant"); for (jint i = 0; i < classes_count; i++) { diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index db534b6df3c..fbe5ee53b93 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -103,7 +103,9 @@ NO_TRANSITION_END NO_TRANSITION(void, jfr_set_enabled(JNIEnv* env, jclass jvm, jlong event_type_id, jboolean enabled)) JfrEventSetting::set_enabled(event_type_id, JNI_TRUE == enabled); if (EventOldObjectSample::eventId == event_type_id) { - ThreadInVMfromNative transition(JavaThread::thread_from_jni_environment(env)); + JavaThread* thread = JavaThread::thread_from_jni_environment(env); + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); + ThreadInVMfromNative transition(thread); if (JNI_TRUE == enabled) { LeakProfiler::start(JfrOptionSet::old_object_queue_size()); } else { diff --git a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp index 49f7719d00d..d9f90ee1153 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp @@ -291,6 +291,7 @@ void JfrStorage::register_full(BufferPtr buffer, Thread* thread) { JavaThread* jt = JavaThread::cast(thread); if (jt->thread_state() == _thread_in_native) { // Transition java thread to vm so it can issue a notify. + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt)); ThreadInVMfromNative transition(jt); _post_box.post(MSG_FULLBUFFER); return; diff --git a/src/hotspot/share/jfr/support/jfrIntrinsics.cpp b/src/hotspot/share/jfr/support/jfrIntrinsics.cpp index acc640077d4..4b7c6c8aee9 100644 --- a/src/hotspot/share/jfr/support/jfrIntrinsics.cpp +++ b/src/hotspot/share/jfr/support/jfrIntrinsics.cpp @@ -56,6 +56,7 @@ void* JfrIntrinsicSupport::write_checkpoint(JavaThread* jt) { assert(JfrThreadLocal::is_vthread(jt), "invariant"); const u2 vthread_thread_local_epoch = JfrThreadLocal::vthread_epoch(jt); const u2 current_epoch = ThreadIdAccess::current_epoch(); + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt)); if (vthread_thread_local_epoch == current_epoch) { // After the epoch test in the intrinsic, the thread sampler interleaved // and suspended the thread. As part of taking a sample, it updated diff --git a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp index 9b27f06df7a..2bd66ce7c1c 100644 --- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp +++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp @@ -123,6 +123,7 @@ void JfrJavaEventWriter::flush(jobject writer, jint used, jint requested, JavaTh u1* const new_current_position = is_valid ? buffer->pos() + used : buffer->pos(); assert(start_pos_offset != invalid_offset, "invariant"); // can safepoint here + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt)); ThreadInVMfromNative transition(jt); oop const w = JNIHandles::resolve_non_null(writer); assert(w != nullptr, "invariant"); diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index eee5b2a70fa..5f826b4045a 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -382,6 +382,7 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) { if (JvmtiEnv::get_phase() == JVMTI_PHASE_LIVE) { JavaThread* current_thread = JavaThread::current(); // transition code: native to VM + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread)); ThreadInVMfromNative __tiv(current_thread); VM_ENTRY_BASE(jvmtiEnv*, JvmtiExport::get_jvmti_interface, current_thread) debug_only(VMNativeEntryWrapper __vew;) diff --git a/src/hotspot/share/prims/jvmtiExtensions.cpp b/src/hotspot/share/prims/jvmtiExtensions.cpp index b40ad7ddbd1..c1767454227 100644 --- a/src/hotspot/share/prims/jvmtiExtensions.cpp +++ b/src/hotspot/share/prims/jvmtiExtensions.cpp @@ -130,6 +130,7 @@ static jvmtiError JNICALL GetCarrierThread(const jvmtiEnv* env, ...) { thread_ptr = va_arg(ap, jthread*); va_end(ap); + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread)); ThreadInVMfromNative tiv(current_thread); JvmtiVTMSTransitionDisabler disabler; From 1188d404bc4879fc388209cd32e6c4e46178e200 Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Thu, 18 Apr 2024 05:42:30 +0000 Subject: [PATCH 3/3] 8323782: Race: Thread::interrupt vs. AbstractInterruptibleChannel.begin Reviewed-by: phh Backport-of: 4018b2b19629ddb8cd7a56e064dfef371f23e5fa --- .../share/classes/java/lang/Thread.java | 13 +-- .../channels/Selector/LotsOfInterrupts.java | 91 +++++++++++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index ec578efd8ab..b9f99fe912c 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -1697,20 +1697,21 @@ public final void stop() { public void interrupt() { if (this != Thread.currentThread()) { checkAccess(); + } + + // Setting the interrupt status must be done before reading nioBlocker. + interrupted = true; + interrupt0(); // inform VM of interrupt - // thread may be blocked in an I/O operation + // thread may be blocked in an I/O operation + if (this != Thread.currentThread()) { synchronized (interruptLock) { Interruptible b = nioBlocker; if (b != null) { - interrupted = true; - interrupt0(); // inform VM of interrupt b.interrupt(this); - return; } } } - interrupted = true; - interrupt0(); // inform VM of interrupt } /** diff --git a/test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java b/test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java new file mode 100644 index 00000000000..98470dec160 --- /dev/null +++ b/test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=platform + * @bug 8323782 + * @summary Stress test Thread.interrupt on a target Thread doing a selection operation + * @run main LotsOfInterrupts 200000 + */ + +/* + * @test id=virtual + * @run main/othervm -DthreadFactory=virtual LotsOfInterrupts 200000 + */ + +import java.nio.channels.Selector; +import java.time.Instant; +import java.util.concurrent.Phaser; +import java.util.concurrent.ThreadFactory; + +public class LotsOfInterrupts { + + public static void main(String[] args) throws Exception { + int iterations; + if (args.length > 0) { + iterations = Integer.parseInt(args[0]); + } else { + iterations = 500_000; + } + + ThreadFactory factory; + String value = System.getProperty("threadFactory"); + if ("virtual".equals(value)) { + factory = Thread.ofVirtual().factory(); + } else { + factory = Thread.ofPlatform().factory(); + } + + var phaser = new Phaser(2); + + Thread thread = factory.newThread(() -> { + try (Selector sel = Selector.open()) { + for (int i = 0; i < iterations; i++) { + phaser.arriveAndAwaitAdvance(); + sel.select(); + + // clear interrupt status and consume wakeup + Thread.interrupted(); + sel.selectNow(); + } + } catch (Throwable ex) { + ex.printStackTrace(); + } + }); + thread.start(); + + long lastTimestamp = System.currentTimeMillis(); + for (int i = 0; i < iterations; i++) { + phaser.arriveAndAwaitAdvance(); + thread.interrupt(); + + long currentTime = System.currentTimeMillis(); + if ((currentTime - lastTimestamp) > 500) { + System.out.format("%s %d iterations remaining ...%n", Instant.now(), (iterations - i)); + lastTimestamp = currentTime; + } + } + + thread.join(); + } +}