Skip to content

Commit 8360312

Browse files
Alan Batemanpull[bot]
authored andcommitted
8315373: Change VirtualThread to unmount after freezing, re-mount before thawing
Reviewed-by: pchilanomate, mgronlun, sspitsyn
1 parent 8b1fdec commit 8360312

File tree

3 files changed

+32
-37
lines changed

3 files changed

+32
-37
lines changed

src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
138138

139139
class JfrVframeStream : public vframeStreamCommon {
140140
private:
141+
bool _vthread;
141142
const ContinuationEntry* _cont_entry;
142143
bool _async_mode;
143-
bool _vthread;
144144
bool step_to_sender();
145145
void next_frame();
146146
public:
@@ -165,8 +165,9 @@ JfrVframeStream::JfrVframeStream(JavaThread* jt, const frame& fr, bool stop_at_j
165165
RegisterMap::UpdateMap::skip,
166166
RegisterMap::ProcessFrames::skip,
167167
walk_continuation(jt))),
168-
_cont_entry(JfrThreadLocal::is_vthread(jt) ? jt->last_continuation() : nullptr),
169-
_async_mode(async_mode), _vthread(JfrThreadLocal::is_vthread(jt)) {
168+
_vthread(JfrThreadLocal::is_vthread(jt)),
169+
_cont_entry(_vthread ? jt->last_continuation() : nullptr),
170+
_async_mode(async_mode) {
170171
assert(!_vthread || _cont_entry != nullptr, "invariant");
171172
_reg_map.set_async(async_mode);
172173
_frame = fr;

src/hotspot/share/jfr/support/jfrThreadLocal.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,14 @@ traceid JfrThreadLocal::thread_id(const Thread* t) {
395395
return t->jfr_thread_local()->_thread_id_alias;
396396
}
397397
JfrThreadLocal* const tl = t->jfr_thread_local();
398-
if (!t->is_Java_thread() || !Atomic::load_acquire(&tl->_vthread)) {
398+
if (!t->is_Java_thread()) {
399399
return jvm_thread_id(t, tl);
400400
}
401-
// virtual thread
402401
const JavaThread* jt = JavaThread::cast(t);
402+
if (!is_vthread(jt)) {
403+
return jvm_thread_id(t, tl);
404+
}
405+
// virtual thread
403406
const traceid tid = vthread_id(jt);
404407
assert(tid != 0, "invariant");
405408
if (!tl->is_vthread_excluded()) {
@@ -456,7 +459,7 @@ traceid JfrThreadLocal::jvm_thread_id(const Thread* t) {
456459

457460
bool JfrThreadLocal::is_vthread(const JavaThread* jt) {
458461
assert(jt != nullptr, "invariant");
459-
return Atomic::load_acquire(&jt->jfr_thread_local()->_vthread);
462+
return Atomic::load_acquire(&jt->jfr_thread_local()->_vthread) && jt->last_continuation() != nullptr;
460463
}
461464

462465
inline bool is_virtual(const JavaThread* jt, oop thread) {

src/java.base/share/classes/java/lang/VirtualThread.java

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,11 @@ public void run() {
194194
}
195195

196196
/**
197-
* Runs or continues execution of the continuation on the current thread.
197+
* Runs or continues execution on the current thread. The virtual thread is mounted
198+
* on the current thread before the task runs or continues. It unmounts when the
199+
* task completes or yields.
198200
*/
201+
@ChangesCurrentThread
199202
private void runContinuation() {
200203
// the carrier must be a platform thread
201204
if (Thread.currentThread().isVirtual()) {
@@ -217,11 +220,13 @@ private void runContinuation() {
217220
// notify JVMTI before mount
218221
notifyJvmtiMount(/*hide*/true);
219222

223+
mount();
220224
try {
221225
cont.run();
222226
} finally {
227+
unmount();
223228
if (cont.isDone()) {
224-
afterTerminate();
229+
afterDone();
225230
} else {
226231
afterYield();
227232
}
@@ -285,16 +290,13 @@ private void submitFailed(RejectedExecutionException ree) {
285290
}
286291

287292
/**
288-
* Runs a task in the context of this virtual thread. The virtual thread is
289-
* mounted on the current (carrier) thread before the task runs. It unmounts
290-
* from its carrier thread when the task completes.
293+
* Runs a task in the context of this virtual thread.
291294
*/
292295
@ChangesCurrentThread
293296
private void run(Runnable task) {
294-
assert state == RUNNING;
297+
assert Thread.currentThread() == this && state == RUNNING;
295298

296-
// first mount
297-
mount();
299+
// notify JVMTI, may post VirtualThreadStart event
298300
notifyJvmtiStart();
299301

300302
// emit JFR event if enabled
@@ -322,12 +324,8 @@ private void run(Runnable task) {
322324
}
323325

324326
} finally {
325-
// last unmount
327+
// notify JVMTI, may post VirtualThreadEnd event
326328
notifyJvmtiEnd();
327-
unmount();
328-
329-
// final state
330-
setState(TERMINATED);
331329
}
332330
}
333331
}
@@ -417,21 +415,15 @@ <V> V executeOnCarrierThread(Callable<V> task) throws Exception {
417415
}
418416

419417
/**
420-
* Unmounts this virtual thread, invokes Continuation.yield, and re-mounts the
421-
* thread when continued. When enabled, JVMTI must be notified from this method.
422-
* @return true if the yield was successful
418+
* Invokes Continuation.yield, notifying JVMTI (if enabled) to hide frames until
419+
* the continuation continues.
423420
*/
424421
@Hidden
425-
@ChangesCurrentThread
426422
private boolean yieldContinuation() {
427-
// unmount
428423
notifyJvmtiUnmount(/*hide*/true);
429-
unmount();
430424
try {
431425
return Continuation.yield(VTHREAD_SCOPE);
432426
} finally {
433-
// re-mount
434-
mount();
435427
notifyJvmtiMount(/*hide*/false);
436428
}
437429
}
@@ -477,22 +469,22 @@ private void afterYield() {
477469
}
478470

479471
/**
480-
* Invoked after the thread terminates execution. It notifies anyone
481-
* waiting for the thread to terminate.
472+
* Invoked after the continuation completes.
482473
*/
483-
private void afterTerminate() {
484-
afterTerminate(true, true);
474+
private void afterDone() {
475+
afterDone(true, true);
485476
}
486477

487478
/**
488-
* Invoked after the thread terminates (or start failed). This method
489-
* notifies anyone waiting for the thread to terminate.
479+
* Invoked after the continuation completes (or start failed). Sets the thread
480+
* state to TERMINATED and notifies anyone waiting for the thread to terminate.
490481
*
491482
* @param notifyContainer true if its container should be notified
492483
* @param executed true if the thread executed, false if it failed to start
493484
*/
494-
private void afterTerminate(boolean notifyContainer, boolean executed) {
495-
assert (state() == TERMINATED) && (carrierThread == null);
485+
private void afterDone(boolean notifyContainer, boolean executed) {
486+
assert carrierThread == null;
487+
setState(TERMINATED);
496488

497489
if (executed) {
498490
notifyJvmtiUnmount(/*hide*/false);
@@ -546,8 +538,7 @@ void start(ThreadContainer container) {
546538
started = true;
547539
} finally {
548540
if (!started) {
549-
setState(TERMINATED);
550-
afterTerminate(addedToContainer, /*executed*/false);
541+
afterDone(addedToContainer, /*executed*/false);
551542
}
552543
}
553544
}

0 commit comments

Comments
 (0)