[External] : Re: : RE: Question about the Method Exit Test

Chris Plummer chris.plummer at oracle.com
Fri Sep 15 02:43:18 UTC 2023


Ok. I missed that it has 3 virtual threads. I suppose the potential for 
the carrier thread switch is there then.


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.


Chris


On 9/14/23 7:39 AM, Babneet B Singh wrote:
> Hi Chris,
>
> The intent of the test makes sense.
>
> The test has three vthreads, 1x PRODUCER and 2x CONSUMER: 
> MethodExitTest.java#L77-L79 
> <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$>.
>
> Also, the implementation of SynchronousQueue changed recently, where 
> the Thread.yield calls were removed to resolve a regression: 
> https://github.com/openjdk/jdk/commit/8d1ab57065c7ebcc650b5fb4ae098f8b0a35f112 
> <https://urldefense.com/v3/__https://github.com/openjdk/jdk/commit/8d1ab57065c7ebcc650b5fb4ae098f8b0a35f112__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes7yMJtrM$>.
>
> The above SynchronousQueue update might prevent the PRODUCER vthread 
> unmount between breakpoint_hit1 and breakpoint_hit2, which I had 
> observed locally.
>
> Regards,
> Babneet
>
>
>
>
> ------------------------------------------------------------------------
> *From:* Chris Plummer <chris.plummer at oracle.com>
> *Sent:* September 13, 2023 5:42 PM
> *To:* Babneet B Singh <sbabneet at ca.ibm.com>; Gengchen Tuo 
> <Gengchen.Tuo at ibm.com>; loom-dev at openjdk.org <loom-dev at openjdk.org>
> *Subject:* Re: [External] : RE: Question about the Method Exit Test
> Hi Babneet,
>
>
> Generally speaking I think your analysis is correct, although
> realistically I don't think the test as written can ever get the
> unexpected MethodExit on the carrier thread. The test is run with
> -Djdk.defaultScheduler.parallelism=2, so that means there will be
> exactly two carrier threads, one for the PRODUCER and one for the
> CONSUMER. Under these circumstances it is hard, and probably impossible,
> to agitate the thread scheduling in such a way that a virtual thread
> ends up being rescheduled on a different carrier thread.
>
>
> Perhaps adding a 3rd virtual thread (that is not related to the first
> two) and having it perform a potentially blocking (and carrier thread
> rescheduling) action (such as a short Thread.sleep()) would cause the
> unexpected MethodExit on the carrier thread. Or maybe allowing for 3
> carrier threads would accomplish this. But even then, the carrier thread
> switch would have to happen during the short period between the two
> breakpoints, so there is only one brief opportunity for the switch to
> happen in a way that would cause the test to fail. In any case, I don't
> think the goal of this test is to test that scenario, so at best would
> be done to prove our understanding the of situation, and maybe used as a
> basis for writing a different test.
>
>
> thanks
>
>
> Chris
>
>
> On 9/13/23 9:39 AM, Babneet B Singh wrote:
> > Hi Chris,
> >
> > Thanks for the explanation. Do you agree with the below analysis? If
> > so, will it be possible to have the test fixed?
> >
> > |vthread| - virtual thread.
> >
> >
> > Between |breakpoint_hit1| and |breakpoint_hit2|, the test doesn't
> > expect the |PRODUCER vthread's carrier thread| to *RUN*. So, the test
> > explicitly checks that no |JVMTI MethodExit event| is triggered by the
> > |PRODUCER vthread's carrier thread|.
> >
> > I feel that this check is incorrect because the |PRODUCER vthread|
> > |unmounts| and |mounts| between |breakpoint_hit1| and
> > |breakpoint_hit2|. Whenever a |vthread| unmounts, the corresponding
> > carrier thread is mounted and allowed to *RUN*.
> >
> > |PRODUCER vthread| |unmounts| while inserting an element to the
> > SynchronousQueue
> > 
> <https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/util/concurrent/SynchronousQueue.html 
> <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-$>>, 
>
> > which is a blocking queue. Insert and remove operations are
> > synchronized. |vthread| seems to yield and unmount if it has to wait
> > on such an operation. Below is the PRODUCER vthread's stack trace
> > during the |VirtualThreadUnmount event, which happens between
> > breakpoint_hit1| and |breakpoint_hit2.|
> >
> > |Hit #1: VirtualThreadUnmount #340: enabling FramePop for method:
> > java/lang/VirtualThread::notifyJvmtiUnmount on virtual thread:
> > 0x27e640 VirtualThreadUnmount #340: method:
> > java/lang/VirtualThread::notifyJvmtiUnmount, thread: VT-PRODUCER#0
> > JVMTI Stack Trace for thread VT-PRODUCER#0: frame count: 12  0:
> > java/lang/VirtualThread: yieldContinuation()Z  1:
> > java/lang/VirtualThread: tryYield()V  2: java/lang/Thread: yield()V
> >  3: java/util/concurrent/SynchronousQueue$TransferStack:
> > transfer(Ljava/lang/Object;ZJ)Ljava/lang/Object;  4:
> > java/util/concurrent/SynchronousQueue: put(Ljava/lang/Object;)V  5:
> > MethodExitTest: qPut(Ljava/lang/String;)V  6: MethodExitTest:
> > lambda$static$0()V  7: MethodExitTest$$Lambda.0x00000000d7030b98:
> > run()V  8: java/lang/VirtualThread:
> > runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V  9:
> > java/lang/VirtualThread: run(Ljava/lang/Runnable;)V 10:
> > java/lang/VirtualThread$VThreadContinuation$1: run()V 11:
> > jdk/internal/vm/Continuation: enter(Ljdk/internal/vm/Continuation;)V|
> > Regards,
> > Babneet
> >
> >
> > ------------------------------------------------------------------------
> > *From:* loom-dev <loom-dev-retn at openjdk.org> on behalf of Chris
> > Plummer <chris.plummer at oracle.com>
> > *Sent:* August 8, 2023 6:21 PM
> > *To:* Gengchen Tuo <Gengchen.Tuo at ibm.com>; loom-dev at openjdk.org
> > <loom-dev at openjdk.org>
> > *Subject:* [EXTERNAL] Re: Question about the Method Exit Test
> > When the first breakpoint is hit, METHOD_EXIT is enabled, but it is only
> > enabled on the carrier thread. Since we are only executing on the
> > virtual thread when the breakpoint is hit, no METHOD_EXIT event should
> > be generated.
> >
> >      // Enable METHOD_EXIT events on the cthread. We should not get one.
> >      LOG("Hit #1: Breakpoint: %s: enabling MethodExit events on carrier
> > thread: %p\n",
> >             mname, (void*)cthread);
> >      set_event_notification_mode(jvmti, jni, JVMTI_ENABLE,
> > JVMTI_EVENT_METHOD_EXIT, cthread);
> >
> > When the 2nd breakpoint is hit, that is when we enable METHOD_EXIT on
> > the virtual thread:
> >
> >    // Enable METHOD_EXIT events on the vthread. We should get one.
> >    LOG("Hit #2: Breakpoint: %s: enabling MethodExit events on %s thread:
> > %p\n",
> >            mname, is_virtual ? "virtual" : "carrier", (void*)thread);
> >    set_event_notification_mode(jvmti, jni, JVMTI_ENABLE,
> > JVMTI_EVENT_METHOD_EXIT, thread);
> >
> > So now we will see METHOD_EXIT events. I don't think this has anything
> > to do with lines 59-60, which have to do with deferring the enabling of
> > the initial breakpoint until after a warmup period:
> >
> > if (i == MSG_COUNT - 10) {
> >                      // Once we have warmed up, enable the first
> > breakpoint which eventually will
> >                      // lead to enabling single stepping.
> > enableEvents(Thread.currentThread(),
> > MethodExitTest.class);
> >                  }
> >
> > My guess is this because we have 3 threads in play, and want to make
> > sure they are all executing in the virtual thread before enabling
> > METHOD_EXIT events.
> >
> > And I think it's safe to say you can ignore the "single stepping"
> > comment. This test was cloned from one of our very early jvmti virtual
> > threads tests, and that comment appears to be a relic. There is also a
> > reference in the C file that can go away:
> >
> >    if (strcmp(event_name, "SingleStep") != 0) {
> >      print_stack_trace(jvmti, jni, thread);
> >    }
> >
> > Chris
> >
> > On 8/8/23 12:35 PM, Gengchen Tuo wrote:
> > >
> > > Hi all. In the Method Exit test
> > >
> > 
> https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java 
> <https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes6xehAzx$> 
>
> > 
> <https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java 
> <https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/serviceability/jvmti/vthread/MethodExitTest/MethodExitTest.java__;!!ACWV5N9M2RV99hQ!NuDzF6kfdbllKutV7CxopfxcBNb1g9Kw7Z_EMqi0kGYyvc2zDRkF9o2Ija2eq23IY3V0qwSNr-Mes6xehAzx$>> 
>
> > ,
> > > no MethodExit event is expected between the first and the second
> > > breakpoint hit. Why are we making this assumption? Maybe that’s
> > > related to line 59 and 60 that I don’t really understand? To my
> > > knowledge, the producer thread may yield between the two breakpoint
> > > hits and MethodExit events will be reported.
> > >
> > >
> > >
> > > I tried to enable the MethodEntry event in the agent code and the test
> > > started to fail but this shouldn’t affect the test result I believe?
> > >
> > >
> > >
> > > Thanks in advance
> > >
> > > Gengchen
> > >
> > >
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20230914/5fe7b511/attachment-0001.htm>


More information about the loom-dev mailing list