< prev index next >
src/hotspot/share/runtime/mutex.cpp
Print this page
rev 47400 : [mq]: cmpxchg_ptr
rev 47404 : [mq]: load_ptr_acquire
rev 47406 : [mq]: assembler_cmpxchg
rev 47407 : [mq]: casptr
@@ -249,16 +249,10 @@
// 6. JVMTI raw monitors -- distinct from (5) despite having a confusingly
// similar name.
//
// o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
-
-// CASPTR() uses the canonical argument order that dominates in the literature.
-// Our internal cmpxchg_ptr() uses a bastardized ordering to accommodate Sun .il templates.
-
-#define CASPTR(a, c, s) \
- intptr_t(Atomic::cmpxchg_ptr((void *)(s), (void *)(a), (void *)(c)))
#define UNS(x) (uintptr_t(x))
#define TRACE(m) \
{ \
static volatile int ctr = 0; \
int x = ++ctr; \
@@ -295,26 +289,26 @@
int Monitor::TryLock() {
intptr_t v = _LockWord.FullWord;
for (;;) {
if ((v & _LBIT) != 0) return 0;
- const intptr_t u = CASPTR(&_LockWord, v, v|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(v|_LBIT, &_LockWord.FullWord, v);
if (v == u) return 1;
v = u;
}
}
int Monitor::TryFast() {
// Optimistic fast-path form ...
// Fast-path attempt for the common uncontended case.
// Avoid RTS->RTO $ coherence upgrade on typical SMP systems.
- intptr_t v = CASPTR(&_LockWord, 0, _LBIT); // agro ...
+ intptr_t v = Atomic::cmpxchg((intptr_t)_LBIT, &_LockWord.FullWord, (intptr_t)0); // agro ...
if (v == 0) return 1;
for (;;) {
if ((v & _LBIT) != 0) return 0;
- const intptr_t u = CASPTR(&_LockWord, v, v|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(v|_LBIT, &_LockWord.FullWord, v);
if (v == u) return 1;
v = u;
}
}
@@ -348,11 +342,11 @@
int SpinMax = NativeMonitorSpinLimit;
int flgs = NativeMonitorFlags;
for (;;) {
intptr_t v = _LockWord.FullWord;
if ((v & _LBIT) == 0) {
- if (CASPTR (&_LockWord, v, v|_LBIT) == v) {
+ if (Atomic::cmpxchg (v|_LBIT, &_LockWord.FullWord, v) == v) {
return 1;
}
continue;
}
@@ -417,17 +411,17 @@
inline int Monitor::AcquireOrPush(ParkEvent * ESelf) {
intptr_t v = _LockWord.FullWord;
for (;;) {
if ((v & _LBIT) == 0) {
- const intptr_t u = CASPTR(&_LockWord, v, v|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(v|_LBIT, &_LockWord.FullWord, v);
if (u == v) return 1; // indicate acquired
v = u;
} else {
// Anticipate success ...
ESelf->ListNext = (ParkEvent *)(v & ~_LBIT);
- const intptr_t u = CASPTR(&_LockWord, v, intptr_t(ESelf)|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(intptr_t(ESelf)|_LBIT, &_LockWord.FullWord, v);
if (u == v) return 0; // indicate pushed onto cxq
v = u;
}
// Interference - LockWord change - just retry
}
@@ -461,22 +455,22 @@
// LockWord encoding = (cxq,LOCKBYTE)
ESelf->reset();
OrderAccess::fence();
// Optional optimization ... try barging on the inner lock
- if ((NativeMonitorFlags & 32) && CASPTR (&_OnDeck, NULL, UNS(ESelf)) == 0) {
+ if ((NativeMonitorFlags & 32) && Atomic::cmpxchg_if_null(ESelf, &_OnDeck)) {
goto OnDeck_LOOP;
}
if (AcquireOrPush(ESelf)) goto Exeunt;
// At any given time there is at most one ondeck thread.
// ondeck implies not resident on cxq and not resident on EntryList
// Only the OnDeck thread can try to acquire -- contend for -- the lock.
// CONSIDER: use Self->OnDeck instead of m->OnDeck.
// Deschedule Self so that others may run.
- while (OrderAccess::load_ptr_acquire(&_OnDeck) != ESelf) {
+ while (OrderAccess::load_acquire(&_OnDeck) != ESelf) {
ParkCommon(ESelf, 0);
}
// Self is now in the OnDeck position and will remain so until it
// manages to acquire the lock.
@@ -568,11 +562,11 @@
// but only one concurrent consumer (detacher of RATs).
// Consider protecting this critical section with schedctl on Solaris.
// Unlike a normal lock, however, the exiting thread "locks" OnDeck,
// picks a successor and marks that thread as OnDeck. That successor
// thread will then clear OnDeck once it eventually acquires the outer lock.
- if (CASPTR (&_OnDeck, NULL, _LBIT) != UNS(NULL)) {
+ if (!Atomic::cmpxchg_if_null((ParkEvent*)_LBIT, &_OnDeck)) {
return;
}
ParkEvent * List = _EntryList;
if (List != NULL) {
@@ -590,11 +584,11 @@
// Pass OnDeck role to w, ensuring that _EntryList has been set first.
// w will clear _OnDeck once it acquires the outer lock.
// Note that once we set _OnDeck that thread can acquire the mutex, proceed
// with its critical section and then enter this code to unlock the mutex. So
// you can have multiple threads active in IUnlock at the same time.
- OrderAccess::release_store_ptr(&_OnDeck, w);
+ OrderAccess::release_store(&_OnDeck, w);
// Another optional optimization ...
// For heavily contended locks it's not uncommon that some other
// thread acquired the lock while this thread was arranging succession.
// Try to defer the unpark() operation - Delegate the responsibility
@@ -614,11 +608,11 @@
// drain RATs from cxq into EntryList
// Detach RATs segment with CAS and then merge into EntryList
for (;;) {
// optional optimization - if locked, the owner is responsible for succession
if (cxq & _LBIT) goto Punt;
- const intptr_t vfy = CASPTR(&_LockWord, cxq, cxq & _LBIT);
+ const intptr_t vfy = Atomic::cmpxchg(cxq & _LBIT, &_LockWord.FullWord, cxq);
if (vfy == cxq) break;
cxq = vfy;
// Interference - LockWord changed - Just retry
// We can see concurrent interference from contending threads
// pushing themselves onto the cxq or from lock-unlock operations.
@@ -691,11 +685,11 @@
// push nfy onto the cxq
for (;;) {
const intptr_t v = _LockWord.FullWord;
assert((v & 0xFF) == _LBIT, "invariant");
nfy->ListNext = (ParkEvent *)(v & ~_LBIT);
- if (CASPTR (&_LockWord, v, UNS(nfy)|_LBIT) == v) break;
+ if (Atomic::cmpxchg(intptr_t(nfy)|_LBIT, &_LockWord.FullWord, v) == v) break;
// interference - _LockWord changed -- just retry
}
// Note that setting Notified before pushing nfy onto the cxq is
// also legal and safe, but the safety properties are much more
// subtle, so for the sake of code stewardship ...
@@ -838,11 +832,11 @@
} else {
// A prior notify() operation moved ESelf from the WaitSet to the cxq.
// ESelf is now on the cxq, EntryList or at the OnDeck position.
// The following fragment is extracted from Monitor::ILock()
for (;;) {
- if (OrderAccess::load_ptr_acquire(&_OnDeck) == ESelf && TrySpin(Self)) break;
+ if (OrderAccess::load_acquire(&_OnDeck) == ESelf && TrySpin(Self)) break;
ParkCommon(ESelf, 0);
}
assert(_OnDeck == ESelf, "invariant");
_OnDeck = NULL;
}
@@ -1056,11 +1050,11 @@
// At any given time there is at most one ondeck thread.
// ondeck implies not resident on cxq and not resident on EntryList
// Only the OnDeck thread can try to acquire -- contend for -- the lock.
// CONSIDER: use Self->OnDeck instead of m->OnDeck.
for (;;) {
- if (OrderAccess::load_ptr_acquire(&_OnDeck) == ESelf && TrySpin(NULL)) break;
+ if (OrderAccess::load_acquire(&_OnDeck) == ESelf && TrySpin(NULL)) break;
ParkCommon(ESelf, 0);
}
assert(_OnDeck == ESelf, "invariant");
_OnDeck = NULL;
< prev index next >