Request for reviews (XS): 7011386: race in objArrayKlass::array_klass_impl
Vladimir Kozlov
vladimir.kozlov at oracle.com
Tue Jan 11 18:44:59 PST 2011
Thank you, David
David Holmes wrote:
> David Holmes said the following on 01/12/11 12:21:
>> Vladimir Kozlov said the following on 01/12/11 09:48:
>>> You are right, I added store_store barriers and make these fields
>>> volatile:
>>>
>>> http://cr.openjdk.java.net/~kvn/7011386/webrev
>>
>> It strikes me as very odd to have to add explicit memory barriers to
>> code that holds two locks while it executes! I understand the problem
>> is that there is a lock-free reader of the values being set. Where is
>> the code that does the lock-free reading of these values?
In objArrayKlass::multi_allocate().
>>
>> Here:
>>
>> 238 ak->set_lower_dimension(this_oop());
>> 239 OrderAccess::storestore();
>> 240 this_oop->set_higher_dimension(ak());
>> 241 OrderAccess::storestore();
>>
>> what is the subsequent store that #241 is ordering with? I think this
>> is either unnecessary, or else is intended to be a full fence() if we
>> are really saying that the store at #240 must be made visible to all
>> other threads.
>
> On further thought I'd say it is unnecessary. Following the barrier
> there will be two mutex releases that involve additional barriers. The
> key requirement is that if you see the store from #240 then you must see
> the store from #238, and the storestore at #239 achieves that.
I was afraid that the store from 240 could be visible to an other thread
only after locks release so that thread could get old value in the next line:
230 ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
Thanks,
Vladimir
>
> David
> -----
>> David
>>
>>> Vladimir
>>>
>>> Tom Rodriguez wrote:
>>>> On Jan 11, 2011, at 11:15 AM, Vladimir Kozlov wrote:
>>>>
>>>>> Tom,
>>>>>
>>>>> Using oop_store() instead of oop_store_without_check()
>>>>> will generate barriers but it is overkill.
>>>>
>>>> Those are gc barriers. I was really referring to fences. The code
>>>> is a classic instance of the double check locking idiom for lazy init:
>>>>
>>>> objArrayKlassHandle ak (THREAD, this_oop->higher_dimension());
>>>> if (ak.is_null()) {
>>>> if (or_null) return NULL;
>>>>
>>>> ResourceMark rm;
>>>> JavaThread *jt = (JavaThread *)THREAD;
>>>> {
>>>> MutexLocker mc(Compile_lock, THREAD); // for vtables
>>>> // Ensure atomic creation of higher dimensions
>>>> MutexLocker mu(MultiArray_lock, THREAD);
>>>>
>>>> // Check if another thread beat us
>>>> ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
>>>> if( ak.is_null() ) {
>>>>
>>>> So doesn't that mean that we need a fence of some kind?
>>>>
>>>> tom
>>>>
>>>>> I think marking receiver as volatile should be enough:
>>>>>
>>>>> void set_higher_dimension(klassOop k) volatile {
>>>>> oop_store_without_check((oop*) &_higher_dimension, (oop) k); }
>>>>> void set_lower_dimension(klassOop k) volatile {
>>>>> oop_store_without_check((oop*) &_lower_dimension, (oop) k); }
>>>>>
>>>>> Thanks,
>>>>> Vladimir
>>>>>
>>>>> Tom Rodriguez wrote:
>>>>>> That look good, though I keep wondering if we need a barrier in
>>>>>> between or if those fields really should be volatile. It seems
>>>>>> like we're playing a little loose with the locking for these lazy
>>>>>> values.
>>>>>> tom
>>>>>> On Jan 11, 2011, at 9:54 AM, Vladimir Kozlov wrote:
>>>>>>> http://cr.openjdk.java.net/~kvn/7011386/webrev
>>>>>>>
>>>>>>> Fixed 7011386: race in objArrayKlass::array_klass_impl
>>>>>>>
>>>>>>> Other threads may access _lower_dimension field before
>>>>>>> it is initialized by thread which holds the lock in
>>>>>>> objArrayKlass::array_klass_impl().
>>>>>>>
>>>>>>> Move _lower_dimension field initialization before
>>>>>>> _higher_dimension.
>>>>
More information about the hotspot-compiler-dev
mailing list