hotspot/src/os/solaris/vm/os_solaris.cpp
changeset 27458 eb5f1b4f01e1
parent 27400 c5955f4b7c84
child 27473 07948a5f8f5c
child 27471 6e56277909f1
equal deleted inserted replaced
27457:adbe834be3a0 27458:eb5f1b4f01e1
  5370 // an appropriate loop.  A litmus test for the correct
  5370 // an appropriate loop.  A litmus test for the correct
  5371 // usage of park is the following: if park() were modified
  5371 // usage of park is the following: if park() were modified
  5372 // to immediately return 0 your code should still work,
  5372 // to immediately return 0 your code should still work,
  5373 // albeit degenerating to a spin loop.
  5373 // albeit degenerating to a spin loop.
  5374 //
  5374 //
  5375 // An interesting optimization for park() is to use a trylock()
  5375 // In a sense, park()-unpark() just provides more polite spinning
  5376 // to attempt to acquire the mutex.  If the trylock() fails
  5376 // and polling with the key difference over naive spinning being
  5377 // then we know that a concurrent unpark() operation is in-progress.
  5377 // that a parked thread needs to be explicitly unparked() in order
  5378 // in that case the park() code could simply set _count to 0
  5378 // to wake up and to poll the underlying condition.
  5379 // and return immediately.  The subsequent park() operation *might*
       
  5380 // return immediately.  That's harmless as the caller of park() is
       
  5381 // expected to loop.  By using trylock() we will have avoided a
       
  5382 // avoided a context switch caused by contention on the per-thread mutex.
       
  5383 //
  5379 //
  5384 // TODO-FIXME:
  5380 // Assumption:
  5385 // 1.  Reconcile Doug's JSR166 j.u.c park-unpark with the
  5381 //    Only one parker can exist on an event, which is why we allocate
  5386 //     objectmonitor implementation.
  5382 //    them per-thread. Multiple unparkers can coexist.
  5387 // 2.  Collapse the JSR166 parker event, and the
       
  5388 //     objectmonitor ParkEvent into a single "Event" construct.
       
  5389 // 3.  In park() and unpark() add:
       
  5390 //     assert (Thread::current() == AssociatedWith).
       
  5391 // 4.  add spurious wakeup injection on a -XX:EarlyParkReturn=N switch.
       
  5392 //     1-out-of-N park() operations will return immediately.
       
  5393 //
  5383 //
  5394 // _Event transitions in park()
  5384 // _Event transitions in park()
  5395 //   -1 => -1 : illegal
  5385 //   -1 => -1 : illegal
  5396 //    1 =>  0 : pass - return immediately
  5386 //    1 =>  0 : pass - return immediately
  5397 //    0 => -1 : block
  5387 //    0 => -1 : block; then set _Event to 0 before returning
       
  5388 //
       
  5389 // _Event transitions in unpark()
       
  5390 //    0 => 1 : just return
       
  5391 //    1 => 1 : just return
       
  5392 //   -1 => either 0 or 1; must signal target thread
       
  5393 //         That is, we can safely transition _Event from -1 to either
       
  5394 //         0 or 1.
  5398 //
  5395 //
  5399 // _Event serves as a restricted-range semaphore.
  5396 // _Event serves as a restricted-range semaphore.
       
  5397 //   -1 : thread is blocked, i.e. there is a waiter
       
  5398 //    0 : neutral: thread is running or ready,
       
  5399 //        could have been signaled after a wait started
       
  5400 //    1 : signaled - thread is running or ready
  5400 //
  5401 //
  5401 // Another possible encoding of _Event would be with
  5402 // Another possible encoding of _Event would be with
  5402 // explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
  5403 // explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
  5403 //
  5404 //
  5404 // TODO-FIXME: add DTRACE probes for:
  5405 // TODO-FIXME: add DTRACE probes for:
  5454   abstime->tv_nsec = usec * 1000;
  5455   abstime->tv_nsec = usec * 1000;
  5455   return abstime;
  5456   return abstime;
  5456 }
  5457 }
  5457 
  5458 
  5458 void os::PlatformEvent::park() {           // AKA: down()
  5459 void os::PlatformEvent::park() {           // AKA: down()
       
  5460   // Transitions for _Event:
       
  5461   //   -1 => -1 : illegal
       
  5462   //    1 =>  0 : pass - return immediately
       
  5463   //    0 => -1 : block; then set _Event to 0 before returning
       
  5464 
  5459   // Invariant: Only the thread associated with the Event/PlatformEvent
  5465   // Invariant: Only the thread associated with the Event/PlatformEvent
  5460   // may call park().
  5466   // may call park().
  5461   assert(_nParked == 0, "invariant");
  5467   assert(_nParked == 0, "invariant");
  5462 
  5468 
  5463   int v;
  5469   int v;
  5495     OrderAccess::fence();
  5501     OrderAccess::fence();
  5496   }
  5502   }
  5497 }
  5503 }
  5498 
  5504 
  5499 int os::PlatformEvent::park(jlong millis) {
  5505 int os::PlatformEvent::park(jlong millis) {
       
  5506   // Transitions for _Event:
       
  5507   //   -1 => -1 : illegal
       
  5508   //    1 =>  0 : pass - return immediately
       
  5509   //    0 => -1 : block; then set _Event to 0 before returning
       
  5510 
  5500   guarantee(_nParked == 0, "invariant");
  5511   guarantee(_nParked == 0, "invariant");
  5501   int v;
  5512   int v;
  5502   for (;;) {
  5513   for (;;) {
  5503     v = _Event;
  5514     v = _Event;
  5504     if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  5515     if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  5540   return ret;
  5551   return ret;
  5541 }
  5552 }
  5542 
  5553 
  5543 void os::PlatformEvent::unpark() {
  5554 void os::PlatformEvent::unpark() {
  5544   // Transitions for _Event:
  5555   // Transitions for _Event:
  5545   //    0 :=> 1
  5556   //    0 => 1 : just return
  5546   //    1 :=> 1
  5557   //    1 => 1 : just return
  5547   //   -1 :=> either 0 or 1; must signal target thread
  5558   //   -1 => either 0 or 1; must signal target thread
  5548   //          That is, we can safely transition _Event from -1 to either
  5559   //         That is, we can safely transition _Event from -1 to either
  5549   //          0 or 1.
  5560   //         0 or 1.
  5550   // See also: "Semaphores in Plan 9" by Mullender & Cox
  5561   // See also: "Semaphores in Plan 9" by Mullender & Cox
  5551   //
  5562   //
  5552   // Note: Forcing a transition from "-1" to "1" on an unpark() means
  5563   // Note: Forcing a transition from "-1" to "1" on an unpark() means
  5553   // that it will take two back-to-back park() calls for the owning
  5564   // that it will take two back-to-back park() calls for the owning
  5554   // thread to block. This has the benefit of forcing a spurious return
  5565   // thread to block. This has the benefit of forcing a spurious return
  5564   int AnyWaiters = _nParked;
  5575   int AnyWaiters = _nParked;
  5565   status = os::Solaris::mutex_unlock(_mutex);
  5576   status = os::Solaris::mutex_unlock(_mutex);
  5566   assert_status(status == 0, status, "mutex_unlock");
  5577   assert_status(status == 0, status, "mutex_unlock");
  5567   guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
  5578   guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
  5568   if (AnyWaiters != 0) {
  5579   if (AnyWaiters != 0) {
  5569     // We intentional signal *after* dropping the lock
  5580     // Note that we signal() *after* dropping the lock for "immortal" Events.
  5570     // to avoid a common class of futile wakeups.
  5581     // This is safe and avoids a common class of  futile wakeups.  In rare
       
  5582     // circumstances this can cause a thread to return prematurely from
       
  5583     // cond_{timed}wait() but the spurious wakeup is benign and the victim
       
  5584     // will simply re-test the condition and re-park itself.
       
  5585     // This provides particular benefit if the underlying platform does not
       
  5586     // provide wait morphing.
  5571     status = os::Solaris::cond_signal(_cond);
  5587     status = os::Solaris::cond_signal(_cond);
  5572     assert_status(status == 0, status, "cond_signal");
  5588     assert_status(status == 0, status, "cond_signal");
  5573   }
  5589   }
  5574 }
  5590 }
  5575 
  5591