hotspot/src/os/linux/vm/os_linux.cpp
changeset 25472 381638db28e6
parent 25468 5331df506290
child 25477 7dad9f95fd31
equal deleted inserted replaced
25471:3ab9867d7786 25472:381638db28e6
  5455     abstime->tv_nsec = usec * 1000;
  5455     abstime->tv_nsec = usec * 1000;
  5456   }
  5456   }
  5457   return abstime;
  5457   return abstime;
  5458 }
  5458 }
  5459 
  5459 
  5460 
       
  5461 // Test-and-clear _Event, always leaves _Event set to 0, returns immediately.
       
  5462 // Conceptually TryPark() should be equivalent to park(0).
       
  5463 
       
  5464 int os::PlatformEvent::TryPark() {
       
  5465   for (;;) {
       
  5466     const int v = _Event;
       
  5467     guarantee((v == 0) || (v == 1), "invariant");
       
  5468     if (Atomic::cmpxchg(0, &_Event, v) == v) return v;
       
  5469   }
       
  5470 }
       
  5471 
       
  5472 void os::PlatformEvent::park() {       // AKA "down()"
  5460 void os::PlatformEvent::park() {       // AKA "down()"
  5473   // Invariant: Only the thread associated with the Event/PlatformEvent
  5461   // Invariant: Only the thread associated with the Event/PlatformEvent
  5474   // may call park().
  5462   // may call park().
  5475   // TODO: assert that _Assoc != NULL or _Assoc == Self
  5463   // TODO: assert that _Assoc != NULL or _Assoc == Self
       
  5464   assert(_nParked == 0, "invariant");
       
  5465 
  5476   int v;
  5466   int v;
  5477   for (;;) {
  5467   for (;;) {
  5478       v = _Event;
  5468       v = _Event;
  5479       if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  5469       if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  5480   }
  5470   }
  5570   // Transitions for _Event:
  5560   // Transitions for _Event:
  5571   //    0 :=> 1
  5561   //    0 :=> 1
  5572   //    1 :=> 1
  5562   //    1 :=> 1
  5573   //   -1 :=> either 0 or 1; must signal target thread
  5563   //   -1 :=> either 0 or 1; must signal target thread
  5574   //          That is, we can safely transition _Event from -1 to either
  5564   //          That is, we can safely transition _Event from -1 to either
  5575   //          0 or 1. Forcing 1 is slightly more efficient for back-to-back
  5565   //          0 or 1.
  5576   //          unpark() calls.
       
  5577   // See also: "Semaphores in Plan 9" by Mullender & Cox
  5566   // See also: "Semaphores in Plan 9" by Mullender & Cox
  5578   //
  5567   //
  5579   // Note: Forcing a transition from "-1" to "1" on an unpark() means
  5568   // Note: Forcing a transition from "-1" to "1" on an unpark() means
  5580   // that it will take two back-to-back park() calls for the owning
  5569   // that it will take two back-to-back park() calls for the owning
  5581   // thread to block. This has the benefit of forcing a spurious return
  5570   // thread to block. This has the benefit of forcing a spurious return
  5799     jt->java_suspend_self();
  5788     jt->java_suspend_self();
  5800   }
  5789   }
  5801 }
  5790 }
  5802 
  5791 
  5803 void Parker::unpark() {
  5792 void Parker::unpark() {
  5804   int s, status;
  5793   int status = pthread_mutex_lock(_mutex);
  5805   status = pthread_mutex_lock(_mutex);
       
  5806   assert(status == 0, "invariant");
  5794   assert(status == 0, "invariant");
  5807   s = _counter;
  5795   const int s = _counter;
  5808   _counter = 1;
  5796   _counter = 1;
  5809   if (s < 1) {
  5797   if (s < 1) {
  5810     // thread might be parked
  5798     // thread might be parked
  5811     if (_cur_index != -1) {
  5799     if (_cur_index != -1) {
  5812       // thread is definitely parked
  5800       // thread is definitely parked