Why is mark read as MO_RELAXED in read_stable_mark()?

Roman Kennke rkennke at redhat.com
Mon Jul 12 19:26:22 UTC 2021


>> Hi Hotspot runtime devs,
>>
>> I am messing a little bit with read_stable_mark() in synchronizer.cpp 
>> in Lilliput project (because I want to load the Klass* from the header).
>>
>> I notice that, in read_stable_mark(), we are loading the header with 
>> MO_RELAXED memory ordering, even though the INFLATING header is stored 
>> either via CAS or (re-)stored with MO_RELEASE. Wouldn't it be more 
>> consequential to load the header with MO_ACQUIRE instead?
> For the monitor case I think we already have an address dependency in 
> the reader so there is no need for the acquire. So we first read the 
> monitor address and then use that address to access the _header 
> field(FastHashCode() case) or _owner field(current_thread_holds_lock() 
> and get_lock_owner() cases). The writer in turn orders the stores to 
> _owner/_header and the publishing of the monitor address by using a 
> release store in inflate() (I think this is the one you are referring to).
> 

Thanks Patricio,

I am not quite sure that I follow you.

On the reader side, given an object, when a thread calls into 
FastHashCode() or any locking that causes inflation, it needs to read 
the object header, and that is always done with a plain read. In 
particular, read_stable_mark() does that, while waiting for the header 
to become != INFLATING. On the writer side, we use CAS (using 
MO_SEQ_CST) to temporarily turn on INFLATING(with release_store() to 
write back the original header, and store with MO_RELEASE to write back 
the original header.

It probably doesn't matter all that much.

I am wondering about this because I am currently moving the Klass* into 
the object header, which means that for klass() implementation, we need 
to load the header similar to how we do it for hashcode(). In particular 
it involves read_stable_mark(). Now, there is a variant of 
klass-accessor that implies acquire-semantics: 
oopDesc::klass_or_null_acquire(). I am not quite sure why exactly we 
need acquire semantics there, but in order to implement it, I believe we 
would have to make a variant of read_stable_mark() that uses acquire 
semantics to load the header, instead of plain reads.

But I'm thinking it may be cleaner overall to always use acquire 
semantics in read_stable_mark() (mirroring the release-store and 
seq-cst-CAS), which would make the acquire-accessors for klass() 
superfluous.

What do you think?



More information about the hotspot-runtime-dev mailing list