synchronization of JVMTI phase notifications [Fwd: Data visibility between threads in Hotspot]
Swamy Venkataramanappa
Swamy.Venkataramanappa at Sun.COM
Wed Feb 18 20:43:37 PST 2009
Hiroshi Yamauchi wrote:
> Thanks for chipping in.
>
> On Fri, Feb 13, 2009 at 9:39 PM, Swamy Venkataramanappa
> <Swamy.Venkataramanappa at sun.com> wrote:
>
>> jvmti spec says no events should be generated after the VM_DEATH.
>>
>> http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html#VMDeath
>>
>> It says: "No event will occur of after this event".
>>
>> I suspect we are posting vm death event too soon. I think we should
>> post vm death after vm thread is destroyed or to the place where all java
>> threads including daemon thread has stopped running.
>>
>
> That may be a good fix for the issue of events sent after the VM death.
>
> Since I couldn't suppress my bug with a SetEventCallbacks call that
> nulls out the callback function table or a SetEventNotificationMode
> call to disable all the events, I think there still is some race
> condition/visibility issue there, independent of the above fix.
>
Yes I agree that there is still some race condition/visibility issue.
We do need your fix for that.
My suggestion is just to avoid using mutex locks in event posting.
Thanks,
-Swamy
>> -Swamy
>>
>> Hiroshi Yamauchi wrote:
>>
>>> Dan,
>>>
>>> On Fri, Feb 13, 2009 at 11:39 AM, Daniel D. Daugherty
>>> <Daniel.Daugherty at sun.com> wrote:
>>>
>>>
>>>
>>>> I'm leaning toward making the two fields volatile and adding the
>>>> appropriate OrderAccess::XXX calls. I vaguely remember an existing
>>>> bug for events posting late. I'm going to see if I can find it.
>>>>
>>>>
>>> Making the fields volatile and adding the OrderAccess:xxx calls isn't
>>> enough because we could see the dead phase change while a loop that
>>> calls the list of callbacks is executing (eg the for loop in
>>> JvmtiExport::post_compiled_method_load). We need to guard at least the
>>> loop and the preceding EVT_TRIG_TRACE in a mutex. That's my take.
>>>
>>> Hiroshi
>>>
>>>
>>>
>>>
>>>> Hiroshi Yamauchi wrote:
>>>>
>>>>
>>>>> Hi Dan,
>>>>>
>>>>> On Wed, Feb 11, 2009 at 12:43 PM, Daniel D. Daugherty
>>>>> <Daniel.Daugherty at sun.com <mailto:Daniel.Daugherty at sun.com>> wrote:
>>>>>
>>>>> I'll chime in on parts of this thread below.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Tim Bell wrote:
>>>>>
>>>>> I don't know the precise answer to this question, so I am
>>>>> forwarding it to the Serviceability list to get a wider audience.
>>>>>
>>>>> -------- Original Message --------
>>>>> Subject: Data visibility between threads in Hotspot
>>>>> Date: Tue, 10 Feb 2009 11:14:24 -0800
>>>>>
>>>>> Hi Tim,
>>>>>
>>>>> I have a Hotspot question. Chuck Rasbold pointed me to you.
>>>>> Feel free to
>>>>> forward this message to other experts at Sun, if needed.
>>>>>
>>>>> If one Hotspot engineer wants to guarantee the immediate
>>>>> visibility of a
>>>>> write to a static variable to reads in other threads (assuming
>>>>> the reads
>>>>> and the writes are properly synchronized via a mutex), what
>>>>> does s/he do?
>>>>>
>>>>> Does the use of MutexLocker guarantee the visibility? It
>>>>> probably does not.
>>>>>
>>>>>
>>>>> I believe that MutexLocker does guarantee the visibility:
>>>>>
>>>>> src/share/vm/runtime/mutexLocker.hpp:
>>>>>
>>>>> 133 // See orderAccess.hpp. We assume throughout the VM that
>>>>> MutexLocker's
>>>>> 134 // and friends constructors do a fence, a lock and an
>>>>> acquire *in that
>>>>> 135 // order*. And that their destructors do a release and
>>>>> unlock, in *that*
>>>>> 136 // order. If their implementations change such that these
>>>>> assumptions
>>>>> 137 // are violated, a whole lot of code will break.
>>>>>
>>>>>
>>>>> OK. That's handy.
>>>>>
>>>>>
>>>>>
>>>>> See src/share/vm/runtime/orderAccess.hpp for the gory details.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> There are several volatile variables in Hotpot, but it may not
>>>>> really
>>>>> work because C++ compilers do not guarantee the visibility or
>>>>> limit the
>>>>> instruction reordering.
>>>>>
>>>>> See the "C++ Volatility" section in
>>>>> src/share/vm/runtime/orderAccess.hpp.
>>>>>
>>>>>
>>>>> It's an interesting header file to read.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> For example, there is the static variable JvmtiEnvBase:_phase
>>>>> which
>>>>> indicates the JVMTI phase in which the JVM is currently in.
>>>>> But AFAICT,
>>>>> there is no synchronization used by the callers of get_phase() and
>>>>> set_phase() and apparently they can be called by multiple
>>>>> threads. Also,
>>>>> the JvmtiEventEnabled::_enabled_bits which is a jlong variable
>>>>> that
>>>>> indicates which events are enabled for a single jvmtiEnv. The
>>>>> writes and
>>>>> reads to it are not synchronized, either. These are race
>>>>> conditions,
>>>>> which implies that some JVMTI event can go off in the dead
>>>>> phase when no
>>>>> events are supposed to go off. I'm actually looking into a bug
>>>>> in a
>>>>> JVMTI agent that I suspect is due to this.
>>>>>
>>>>>
>>>>> It certainly looks like JvmtiEnvBase::_phase should minimally be a
>>>>> volatile; it may also require some sort of synchronization to force
>>>>> the updated values to be visible...
>>>>>
>>>>> JvmtiEventEnabled::_enabled_bits also looks problematic. I'm going
>>>>> to have to mull on both of these and talk to some other folks.
>>>>>
>>>>>
>>>>> The bug that I ran across was a memory corruption crash because a
>>>>> CompiledMethodLoad event happened to be sent (due to this race
>>>>> condition)
>>>>> after Agent_OnUnload call where I had already deallocated the agent's
>>>>> data
>>>>> objects. This happens very rarely (once in every more than 100k runs of
>>>>> a
>>>>> more-or-less javac invocation) but often enough to fix.
>>>>>
>>>>> I have a patch attached, which I used to suppress the bug by avoiding
>>>>> the
>>>>> events to be sent during the dead phase by adding synchronization.
>>>>> Basically
>>>>> I make the _phase variable volatile and I use a mutex to guard event
>>>>> callbacks in the all the post_xxx functions and the phase transition to
>>>>> the
>>>>> dead phase in post_vm_death(). Probably we don't need the volatile as
>>>>> long
>>>>> as the mutex guarantees the visibility. The other phase transitions
>>>>> (onload->primodial->start->live) may not need the same degree of
>>>>> synchronization because events that can be sent in a earlier phase can
>>>>> be
>>>>> sent in the next phase as well.
>>>>>
>>>>> The _enabled_bits and the callback function table will probably need a
>>>>> similar synchronization as well. But the attached patch does not
>>>>> implement
>>>>> it and only ensures that no events are sent during the dead phase. I'd
>>>>> like
>>>>> to get the fix into openjdk in one form or another.
>>>>>
>>>>> Thanks,
>>>>> Hiroshi
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Dan
>>>>>
>>>>>
>>>>>
>>>>> Thanks,
>>>>> Hiroshi
>>>>>
>>>>>
>>>>>
>>>>>
>>
More information about the serviceability-dev
mailing list