diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index ae1e6f812c0..a90ef5328a6 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -1000,6 +1000,11 @@ JVM_ENTRY(jboolean, CoroutineSupport_stealCoroutine(JNIEnv* env, jclass klass, j assert(coro->state() != Coroutine::_current, "running"); CoroutineListLocker cll(coro->thread(), thread); + // check if the source thread and the target thread has been scanned or not + // only if hold the CoroutineListLocker, and has the same scanned state, then we can steal + if (coro->thread()->nmethod_traversals() != thread->nmethod_traversals()) { + return false; + } coro->remove_from_list(coro->thread()->coroutine_list()); coro->insert_into_list(thread->coroutine_list()); // change thread logic diff --git a/src/hotspot/share/runtime/sweeper.cpp b/src/hotspot/share/runtime/sweeper.cpp index 93fac19effe..a87c08c428a 100644 --- a/src/hotspot/share/runtime/sweeper.cpp +++ b/src/hotspot/share/runtime/sweeper.cpp @@ -159,6 +159,9 @@ class NMethodMarkingClosure : public HandshakeClosure { void do_thread(Thread* thread) { if (thread->is_Java_thread() && ! thread->is_Code_cache_sweeper_thread()) { thread->as_Java_thread()->nmethods_do(_cl); + if (EnableCoroutine) { + thread->as_Java_thread()->set_nmethod_traversals(NMethodSweeper::traversal_count()); + } } } }; diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index ac7f703032f..0eb346f105f 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -1107,6 +1107,7 @@ JavaThread::JavaThread() : _coroutine_list(nullptr), _current_coroutine(nullptr), _wisp_preempted(false), + _nmethod_traversals(0), _handshake(this), diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index cf5c8841160..0cb933f7152 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -1047,6 +1047,7 @@ class JavaThread: public Thread { Coroutine* _coroutine_list; Coroutine* _current_coroutine; bool _wisp_preempted; + volatile long _nmethod_traversals; public: volatile int* const coroutine_list_lock() { return &_coroutine_list_lock; } @@ -1055,6 +1056,8 @@ class JavaThread: public Thread { void set_current_coroutine(Coroutine *coro) { _current_coroutine = coro; } bool wisp_preempted() const { return _wisp_preempted; } void set_wisp_preempted(bool b) { _wisp_preempted = b; } + void set_nmethod_traversals(long n) { Atomic::release_store(&_nmethod_traversals, n); } + long nmethod_traversals() const { return Atomic::load_acquire(&_nmethod_traversals); } static ByteSize monitor_chunks_offset() { return byte_offset_of(JavaThread, _monitor_chunks); } static ByteSize current_coroutine_offset() { return byte_offset_of(JavaThread, _current_coroutine); }