Request for reviews (XS): 7011386: race in objArrayKlass::array_klass_impl

Vladimir Kozlov vladimir.kozlov at oracle.com
Tue Jan 11 19:27:46 PST 2011


Thank you, David

I will remove second storestore in 241.

Vladimir

David Holmes wrote:
> Vladimir Kozlov said the following on 01/12/11 12:44:
>> 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().
> 
> Thanks - now I see the DCL pattern that Tom described.
> 
>>>>
>>>> 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());
> 
> I assume you meant at 218, which is the same as 230 but without the lock 
> held. Yes it is possible that 218 won't see the value set at 240 until 
> the lock is released, but that is okay, it will proceed to get the lock 
> and recheck at line 230. The key thing is that if 218 does see the value 
> set at 240 then it must also see the value set at 238 - and the 
> storestore achieves that.
> 
> And of course the same for the change in the other file.
> 
> David
> -----
> 
>> 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