RFR: 8166197: assert(RelaxAssert || w != Thread::current()->_MutexEvent) failed: invariant

Carsten Varming varming at gmail.com
Wed Oct 12 13:21:44 UTC 2016


Dear David,

In line 590 "Pass onDeck to w". I don't understand this part of the
comment. Should it say something like "Pass ownership of _OnDeck and
_EntryList to w".

In line 532 there is a read of _OnDeck and in line 553 there is a read of
_EntryList. Why is it safe not to do a load_acquire of _OnDeck in line 532?

Carsten


On Wed, Oct 12, 2016 at 1:08 AM, David Holmes <david.holmes at oracle.com>
wrote:

> Bug: https://bugs.openjdk.java.net/browse/JDK-8166197
> webrev: http://cr.openjdk.java.net/~dholmes/8166197/webrev/
>
> In IUnlock we have the following succession code to wakeup the "onDeck"
> thread:
>
>  ParkEvent * List = _EntryList;
>   if (List != NULL) {
>     // Transfer the head of the EntryList to the OnDeck position.
>     // Once OnDeck, a thread stays OnDeck until it acquires the lock.
>     // For a given lock there is at most OnDeck thread at any one instant.
>    WakeOne:
>     assert(List == _EntryList, "invariant");
>     ParkEvent * const w = List;
>     assert(RelaxAssert || w != Thread::current()->_MutexEvent,
> "invariant");
>     _EntryList = w->ListNext;
>     // as a diagnostic measure consider setting w->_ListNext = BAD
>     assert(UNS(_OnDeck) == _LBIT, "invariant");
>     _OnDeck = w;  // pass OnDeck to w.
>
> It is critical that the update to _EntryList happens before we set
> _OnDeck, as as soon as _OnDeck is set the selected thread (which need not
> yet have parked) can acquire the mutex, complete its critical section and
> proceed to unlock the mutex, and so execute IUnlock in parallel with the
> original thread. If the write to _EntryList has not yet happened that
> second thread finds itself still at the head of _EntryList and so the
> assert fires. If the write to _EntryList happens after the load "List =
> _EntryList", then the first assert can also fire.
>
> Preferred fix today is to use OrderAccess::release_store(&_OnDeck, w)
> with a matching load_acquire(&_OnDeck) in the ILock code:
>
>   while (_OnDeck != ESelf) {
>     ParkCommon(ESelf, 0);
>   }
>
> and corresponding "raw" lock code. Also fixed a couple of typos.
>
> Thanks,
> David
>


More information about the hotspot-runtime-dev mailing list