<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>