<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Ok. I missed that it has 3 virtual threads. I suppose the
potential for the carrier thread switch is there then. <br>
</p>
<p><br>
</p>
<p>This test is actually based on the very first virtual thread code
I wrote a few years ago when experimenting with debugger support
(I used an IDE to set breakpoints and observe how virtual threads
were being scheduled on the carrier thread), and I think my code
was based on something Alan had done. I recall at the time it was
very hard to get the any of the virtual threads to be scheduled on
a different carrier threads. The two CONSUMER threads end up
sharing a carrier thread and the PRODUCER seems to stay on the
same carrier thread.<br>
</p>
<p><br>
</p>
<p>Chris</p>
<p><br>
</p>
<div class="moz-cite-prefix">On 9/14/23 7:39 AM, Babneet B Singh
wrote:<br>
</div>
<blockquote type="cite" cite="mid:MW5PR15MB5243405F942DF000389D7475F7F7A@MW5PR15MB5243.namprd15.prod.outlook.com">
<style type="text/css" style="display:none;">P {margin-top:0;margin-bottom:0;}</style>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Hi Chris,</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
The intent of the test makes sense.</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
The test has three vthreads, 1x PRODUCER and 2x CONSUMER: <a href="https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/cfa89012ab017f3ae147094e5cab6dfd040ce042/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java*L77-L79__;Iw!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes8bPt6Le$" id="OWAf6d1d87f-dc3d-980b-0412-4d1691c528f7" class="OWAAutoLink" moz-do-not-send="true">MethodExitTest.java#L77-L79</a>.</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Also, the implementation of SynchronousQueue changed recently,
where the Thread.yield calls were removed to resolve a
regression:
<a href="https://urldefense.com/v3/__https://github.com/openjdk/jdk/commit/8d1ab57065c7ebcc650b5fb4ae098f8b0a35f112__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes7yMJtrM$" id="LPNoLPOWALinkPreview_3" moz-do-not-send="true">https://github.com/openjdk/jdk/commit/8d1ab57065c7ebcc650b5fb4ae098f8b0a35f112</a>.</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif;
font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
The above SynchronousQueue update might prevent the PRODUCER
vthread unmount between breakpoint_hit1 and breakpoint_hit2,
which I had observed locally.</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Regards,</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Babneet</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Calibri, Arial,
Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b> Chris
Plummer <a class="moz-txt-link-rfc2396E" href="mailto:chris.plummer@oracle.com"><chris.plummer@oracle.com></a><br>
<b>Sent:</b> September 13, 2023 5:42 PM<br>
<b>To:</b> Babneet B Singh <a class="moz-txt-link-rfc2396E" href="mailto:sbabneet@ca.ibm.com"><sbabneet@ca.ibm.com></a>;
Gengchen Tuo <a class="moz-txt-link-rfc2396E" href="mailto:Gengchen.Tuo@ibm.com"><Gengchen.Tuo@ibm.com></a>;
<a class="moz-txt-link-abbreviated" href="mailto:loom-dev@openjdk.org">loom-dev@openjdk.org</a> <a class="moz-txt-link-rfc2396E" href="mailto:loom-dev@openjdk.org"><loom-dev@openjdk.org></a><br>
<b>Subject:</b> Re: [External] : RE: Question about the Method
Exit Test</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Hi Babneet,<br>
<br>
<br>
Generally speaking I think your analysis is correct,
although <br>
realistically I don't think the test as written can ever
get the <br>
unexpected MethodExit on the carrier thread. The test is
run with <br>
-Djdk.defaultScheduler.parallelism=2, so that means there
will be <br>
exactly two carrier threads, one for the PRODUCER and one
for the <br>
CONSUMER. Under these circumstances it is hard, and
probably impossible, <br>
to agitate the thread scheduling in such a way that a
virtual thread <br>
ends up being rescheduled on a different carrier thread.<br>
<br>
<br>
Perhaps adding a 3rd virtual thread (that is not related
to the first <br>
two) and having it perform a potentially blocking (and
carrier thread <br>
rescheduling) action (such as a short Thread.sleep())
would cause the <br>
unexpected MethodExit on the carrier thread. Or maybe
allowing for 3 <br>
carrier threads would accomplish this. But even then, the
carrier thread <br>
switch would have to happen during the short period
between the two <br>
breakpoints, so there is only one brief opportunity for
the switch to <br>
happen in a way that would cause the test to fail. In any
case, I don't <br>
think the goal of this test is to test that scenario, so
at best would <br>
be done to prove our understanding the of situation, and
maybe used as a <br>
basis for writing a different test.<br>
<br>
<br>
thanks<br>
<br>
<br>
Chris<br>
<br>
<br>
On 9/13/23 9:39 AM, Babneet B Singh wrote:<br>
> Hi Chris,<br>
><br>
> Thanks for the explanation. Do you agree with the
below analysis? If <br>
> so, will it be possible to have the test fixed?<br>
><br>
> |vthread| - virtual thread.<br>
><br>
><br>
> Between |breakpoint_hit1| and |breakpoint_hit2|, the
test doesn't <br>
> expect the |PRODUCER vthread's carrier thread| to
*RUN*. So, the test <br>
> explicitly checks that no |JVMTI MethodExit event| is
triggered by the <br>
> |PRODUCER vthread's carrier thread|.<br>
><br>
> I feel that this check is incorrect because the
|PRODUCER vthread| <br>
> |unmounts| and |mounts| between |breakpoint_hit1| and
<br>
> |breakpoint_hit2|. Whenever a |vthread| unmounts, the
corresponding <br>
> carrier thread is mounted and allowed to *RUN*.<br>
><br>
> |PRODUCER vthread| |unmounts| while inserting an
element to the <br>
> SynchronousQueue <br>
> <<a href="https://urldefense.com/v3/__https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/util/concurrent/SynchronousQueue.html__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes7Gb4jA-$" moz-do-not-send="true">https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/util/concurrent/SynchronousQueue.html</a>>,
<br>
> which is a blocking queue. Insert and remove
operations are <br>
> synchronized. |vthread| seems to yield and unmount if
it has to wait <br>
> on such an operation. Below is the PRODUCER vthread's
stack trace <br>
> during the |VirtualThreadUnmount event, which happens
between <br>
> breakpoint_hit1| and |breakpoint_hit2.|<br>
><br>
> |Hit #1: VirtualThreadUnmount #340: enabling FramePop
for method: <br>
> java/lang/VirtualThread::notifyJvmtiUnmount on
virtual thread: <br>
> 0x27e640 VirtualThreadUnmount #340: method: <br>
> java/lang/VirtualThread::notifyJvmtiUnmount, thread:
VT-PRODUCER#0 <br>
> JVMTI Stack Trace for thread VT-PRODUCER#0: frame
count: 12 0: <br>
> java/lang/VirtualThread: yieldContinuation()Z 1: <br>
> java/lang/VirtualThread: tryYield()V 2:
java/lang/Thread: yield()V <br>
> 3:
java/util/concurrent/SynchronousQueue$TransferStack: <br>
> transfer(Ljava/lang/Object;ZJ)Ljava/lang/Object; 4:
<br>
> java/util/concurrent/SynchronousQueue:
put(Ljava/lang/Object;)V 5: <br>
> MethodExitTest: qPut(Ljava/lang/String;)V 6:
MethodExitTest: <br>
> lambda$static$0()V 7:
MethodExitTest$$Lambda.0x00000000d7030b98: <br>
> run()V 8: java/lang/VirtualThread: <br>
> runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V 9:
<br>
> java/lang/VirtualThread: run(Ljava/lang/Runnable;)V
10: <br>
> java/lang/VirtualThread$VThreadContinuation$1: run()V
11: <br>
> jdk/internal/vm/Continuation:
enter(Ljdk/internal/vm/Continuation;)V|<br>
> Regards,<br>
> Babneet<br>
><br>
><br>
>
------------------------------------------------------------------------<br>
> *From:* loom-dev <a class="moz-txt-link-rfc2396E" href="mailto:loom-dev-retn@openjdk.org"><loom-dev-retn@openjdk.org></a> on
behalf of Chris <br>
> Plummer <a class="moz-txt-link-rfc2396E" href="mailto:chris.plummer@oracle.com"><chris.plummer@oracle.com></a><br>
> *Sent:* August 8, 2023 6:21 PM<br>
> *To:* Gengchen Tuo <a class="moz-txt-link-rfc2396E" href="mailto:Gengchen.Tuo@ibm.com"><Gengchen.Tuo@ibm.com></a>;
<a class="moz-txt-link-abbreviated" href="mailto:loom-dev@openjdk.org">loom-dev@openjdk.org</a> <br>
> <a class="moz-txt-link-rfc2396E" href="mailto:loom-dev@openjdk.org"><loom-dev@openjdk.org></a><br>
> *Subject:* [EXTERNAL] Re: Question about the Method
Exit Test<br>
> When the first breakpoint is hit, METHOD_EXIT is
enabled, but it is only<br>
> enabled on the carrier thread. Since we are only
executing on the<br>
> virtual thread when the breakpoint is hit, no
METHOD_EXIT event should<br>
> be generated.<br>
><br>
> // Enable METHOD_EXIT events on the cthread. We
should not get one.<br>
> LOG("Hit #1: Breakpoint: %s: enabling MethodExit
events on carrier<br>
> thread: %p\n",<br>
> mname, (void*)cthread);<br>
> set_event_notification_mode(jvmti, jni,
JVMTI_ENABLE,<br>
> JVMTI_EVENT_METHOD_EXIT, cthread);<br>
><br>
> When the 2nd breakpoint is hit, that is when we
enable METHOD_EXIT on<br>
> the virtual thread:<br>
><br>
> // Enable METHOD_EXIT events on the vthread. We
should get one.<br>
> LOG("Hit #2: Breakpoint: %s: enabling MethodExit
events on %s thread:<br>
> %p\n",<br>
> mname, is_virtual ? "virtual" : "carrier",
(void*)thread);<br>
> set_event_notification_mode(jvmti, jni,
JVMTI_ENABLE,<br>
> JVMTI_EVENT_METHOD_EXIT, thread);<br>
><br>
> So now we will see METHOD_EXIT events. I don't think
this has anything<br>
> to do with lines 59-60, which have to do with
deferring the enabling of<br>
> the initial breakpoint until after a warmup period:<br>
><br>
> if (i == MSG_COUNT - 10) {<br>
> // Once we have warmed up,
enable the first<br>
> breakpoint which eventually will<br>
> // lead to enabling single
stepping.<br>
>
enableEvents(Thread.currentThread(),<br>
> MethodExitTest.class);<br>
> }<br>
><br>
> My guess is this because we have 3 threads in play,
and want to make<br>
> sure they are all executing in the virtual thread
before enabling<br>
> METHOD_EXIT events.<br>
><br>
> And I think it's safe to say you can ignore the
"single stepping"<br>
> comment. This test was cloned from one of our very
early jvmti virtual<br>
> threads tests, and that comment appears to be a
relic. There is also a<br>
> reference in the C file that can go away:<br>
><br>
> if (strcmp(event_name, "SingleStep") != 0) {<br>
> print_stack_trace(jvmti, jni, thread);<br>
> }<br>
><br>
> Chris<br>
><br>
> On 8/8/23 12:35 PM, Gengchen Tuo wrote:<br>
> ><br>
> > Hi all. In the Method Exit test<br>
> > <br>
> <a href="https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes6xehAzx$" moz-do-not-send="true">https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java</a>
<br>
> <<a href="https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes6xehAzx$" moz-do-not-send="true">https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java</a>>
<br>
> ,<br>
> > no MethodExit event is expected between the
first and the second<br>
> > breakpoint hit. Why are we making this
assumption? Maybe that’s<br>
> > related to line 59 and 60 that I don’t really
understand? To my<br>
> > knowledge, the producer thread may yield between
the two breakpoint<br>
> > hits and MethodExit events will be reported.<br>
> ><br>
> ><br>
> ><br>
> > I tried to enable the MethodEntry event in the
agent code and the test<br>
> > started to fail but this shouldn’t affect the
test result I believe?<br>
> ><br>
> ><br>
> ><br>
> > Thanks in advance<br>
> ><br>
> > Gengchen<br>
> ><br>
> ><br>
</div>
</span></font></div>
</blockquote>
</body>
</html>