src/hotspot/share/runtime/thread.cpp
changeset 58243 c67f514fdd54
parent 58226 408c445d04e8
child 58249 e17143e28542
child 58279 448fe2bfd505
equal deleted inserted replaced
58242:94bb65cb37d3 58243:c67f514fdd54
  4990       Self->park();
  4990       Self->park();
  4991     }
  4991     }
  4992   }
  4992   }
  4993 }
  4993 }
  4994 
  4994 
  4995 void Thread::muxAcquireW(volatile intptr_t * Lock, ParkEvent * ev) {
       
  4996   intptr_t w = Atomic::cmpxchg(LOCKBIT, Lock, (intptr_t)0);
       
  4997   if (w == 0) return;
       
  4998   if ((w & LOCKBIT) == 0 && Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
       
  4999     return;
       
  5000   }
       
  5001 
       
  5002   ParkEvent * ReleaseAfter = NULL;
       
  5003   if (ev == NULL) {
       
  5004     ev = ReleaseAfter = ParkEvent::Allocate(NULL);
       
  5005   }
       
  5006   assert((intptr_t(ev) & LOCKBIT) == 0, "invariant");
       
  5007   for (;;) {
       
  5008     guarantee(ev->OnList == 0, "invariant");
       
  5009     int its = (os::is_MP() ? 100 : 0) + 1;
       
  5010 
       
  5011     // Optional spin phase: spin-then-park strategy
       
  5012     while (--its >= 0) {
       
  5013       w = *Lock;
       
  5014       if ((w & LOCKBIT) == 0 && Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
       
  5015         if (ReleaseAfter != NULL) {
       
  5016           ParkEvent::Release(ReleaseAfter);
       
  5017         }
       
  5018         return;
       
  5019       }
       
  5020     }
       
  5021 
       
  5022     ev->reset();
       
  5023     ev->OnList = intptr_t(Lock);
       
  5024     // The following fence() isn't _strictly necessary as the subsequent
       
  5025     // CAS() both serializes execution and ratifies the fetched *Lock value.
       
  5026     OrderAccess::fence();
       
  5027     for (;;) {
       
  5028       w = *Lock;
       
  5029       if ((w & LOCKBIT) == 0) {
       
  5030         if (Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
       
  5031           ev->OnList = 0;
       
  5032           // We call ::Release while holding the outer lock, thus
       
  5033           // artificially lengthening the critical section.
       
  5034           // Consider deferring the ::Release() until the subsequent unlock(),
       
  5035           // after we've dropped the outer lock.
       
  5036           if (ReleaseAfter != NULL) {
       
  5037             ParkEvent::Release(ReleaseAfter);
       
  5038           }
       
  5039           return;
       
  5040         }
       
  5041         continue;      // Interference -- *Lock changed -- Just retry
       
  5042       }
       
  5043       assert(w & LOCKBIT, "invariant");
       
  5044       ev->ListNext = (ParkEvent *) (w & ~LOCKBIT);
       
  5045       if (Atomic::cmpxchg(intptr_t(ev)|LOCKBIT, Lock, w) == w) break;
       
  5046     }
       
  5047 
       
  5048     while (ev->OnList != 0) {
       
  5049       ev->park();
       
  5050     }
       
  5051   }
       
  5052 }
       
  5053 
       
  5054 // Release() must extract a successor from the list and then wake that thread.
  4995 // Release() must extract a successor from the list and then wake that thread.
  5055 // It can "pop" the front of the list or use a detach-modify-reattach (DMR) scheme
  4996 // It can "pop" the front of the list or use a detach-modify-reattach (DMR) scheme
  5056 // similar to that used by ParkEvent::Allocate() and ::Release().  DMR-based
  4997 // similar to that used by ParkEvent::Allocate() and ::Release().  DMR-based
  5057 // Release() would :
  4998 // Release() would :
  5058 // (A) CAS() or swap() null to *Lock, releasing the lock and detaching the list.
  4999 // (A) CAS() or swap() null to *Lock, releasing the lock and detaching the list.