< prev index next >

src/hotspot/os/solaris/os_solaris.cpp

Print this page




4780   // correctly with each other.
4781   OrderAccess::fence();
4782   return ret;
4783 }
4784 
4785 void os::PlatformEvent::unpark() {
4786   // Transitions for _Event:
4787   //    0 => 1 : just return
4788   //    1 => 1 : just return
4789   //   -1 => either 0 or 1; must signal target thread
4790   //         That is, we can safely transition _Event from -1 to either
4791   //         0 or 1.
4792   // See also: "Semaphores in Plan 9" by Mullender & Cox
4793   //
4794   // Note: Forcing a transition from "-1" to "1" on an unpark() means
4795   // that it will take two back-to-back park() calls for the owning
4796   // thread to block. This has the benefit of forcing a spurious return
4797   // from the first park() call after an unpark() call which will help
4798   // shake out uses of park() and unpark() without condition variables.
4799 
4800   if (Atomic::xchg(1, &_Event) >= 0) return;
4801 
4802   // If the thread associated with the event was parked, wake it.
4803   // Wait for the thread assoc with the PlatformEvent to vacate.
4804   int status = os::Solaris::mutex_lock(_mutex);
4805   assert_status(status == 0, status, "mutex_lock");
4806   int AnyWaiters = _nParked;
4807   status = os::Solaris::mutex_unlock(_mutex);
4808   assert_status(status == 0, status, "mutex_unlock");
4809   guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
4810   if (AnyWaiters != 0) {
4811     // Note that we signal() *after* dropping the lock for "immortal" Events.
4812     // This is safe and avoids a common class of  futile wakeups.  In rare
4813     // circumstances this can cause a thread to return prematurely from
4814     // cond_{timed}wait() but the spurious wakeup is benign and the victim
4815     // will simply re-test the condition and re-park itself.
4816     // This provides particular benefit if the underlying platform does not
4817     // provide wait morphing.
4818     status = os::Solaris::cond_signal(_cond);
4819     assert_status(status == 0, status, "cond_signal");
4820   }


4879       if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
4880         absTime->tv_nsec -= NANOSECS_PER_SEC;
4881         ++absTime->tv_sec; // note: this must be <= max_secs
4882       }
4883     }
4884   }
4885   assert(absTime->tv_sec >= 0, "tv_sec < 0");
4886   assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs");
4887   assert(absTime->tv_nsec >= 0, "tv_nsec < 0");
4888   assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec");
4889 }
4890 
4891 void Parker::park(bool isAbsolute, jlong time) {
4892   // Ideally we'd do something useful while spinning, such
4893   // as calling unpackTime().
4894 
4895   // Optional fast-path check:
4896   // Return immediately if a permit is available.
4897   // We depend on Atomic::xchg() having full barrier semantics
4898   // since we are doing a lock-free update to _counter.
4899   if (Atomic::xchg(0, &_counter) > 0) return;
4900 
4901   // Optional fast-exit: Check interrupt before trying to wait
4902   Thread* thread = Thread::current();
4903   assert(thread->is_Java_thread(), "Must be JavaThread");
4904   JavaThread *jt = (JavaThread *)thread;
4905   if (jt->is_interrupted(false)) {
4906     return;
4907   }
4908 
4909   // First, demultiplex/decode time arguments
4910   timespec absTime;
4911   if (time < 0 || (isAbsolute && time == 0)) { // don't wait at all
4912     return;
4913   }
4914   if (time > 0) {
4915     // Warning: this code might be exposed to the old Solaris time
4916     // round-down bugs.  Grep "roundingFix" for details.
4917     unpackTime(&absTime, isAbsolute, time);
4918   }
4919 




4780   // correctly with each other.
4781   OrderAccess::fence();
4782   return ret;
4783 }
4784 
4785 void os::PlatformEvent::unpark() {
4786   // Transitions for _Event:
4787   //    0 => 1 : just return
4788   //    1 => 1 : just return
4789   //   -1 => either 0 or 1; must signal target thread
4790   //         That is, we can safely transition _Event from -1 to either
4791   //         0 or 1.
4792   // See also: "Semaphores in Plan 9" by Mullender & Cox
4793   //
4794   // Note: Forcing a transition from "-1" to "1" on an unpark() means
4795   // that it will take two back-to-back park() calls for the owning
4796   // thread to block. This has the benefit of forcing a spurious return
4797   // from the first park() call after an unpark() call which will help
4798   // shake out uses of park() and unpark() without condition variables.
4799 
4800   if (Atomic::xchg(&_Event, 1) >= 0) return;
4801 
4802   // If the thread associated with the event was parked, wake it.
4803   // Wait for the thread assoc with the PlatformEvent to vacate.
4804   int status = os::Solaris::mutex_lock(_mutex);
4805   assert_status(status == 0, status, "mutex_lock");
4806   int AnyWaiters = _nParked;
4807   status = os::Solaris::mutex_unlock(_mutex);
4808   assert_status(status == 0, status, "mutex_unlock");
4809   guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
4810   if (AnyWaiters != 0) {
4811     // Note that we signal() *after* dropping the lock for "immortal" Events.
4812     // This is safe and avoids a common class of  futile wakeups.  In rare
4813     // circumstances this can cause a thread to return prematurely from
4814     // cond_{timed}wait() but the spurious wakeup is benign and the victim
4815     // will simply re-test the condition and re-park itself.
4816     // This provides particular benefit if the underlying platform does not
4817     // provide wait morphing.
4818     status = os::Solaris::cond_signal(_cond);
4819     assert_status(status == 0, status, "cond_signal");
4820   }


4879       if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
4880         absTime->tv_nsec -= NANOSECS_PER_SEC;
4881         ++absTime->tv_sec; // note: this must be <= max_secs
4882       }
4883     }
4884   }
4885   assert(absTime->tv_sec >= 0, "tv_sec < 0");
4886   assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs");
4887   assert(absTime->tv_nsec >= 0, "tv_nsec < 0");
4888   assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec");
4889 }
4890 
4891 void Parker::park(bool isAbsolute, jlong time) {
4892   // Ideally we'd do something useful while spinning, such
4893   // as calling unpackTime().
4894 
4895   // Optional fast-path check:
4896   // Return immediately if a permit is available.
4897   // We depend on Atomic::xchg() having full barrier semantics
4898   // since we are doing a lock-free update to _counter.
4899   if (Atomic::xchg(&_counter, 0) > 0) return;
4900 
4901   // Optional fast-exit: Check interrupt before trying to wait
4902   Thread* thread = Thread::current();
4903   assert(thread->is_Java_thread(), "Must be JavaThread");
4904   JavaThread *jt = (JavaThread *)thread;
4905   if (jt->is_interrupted(false)) {
4906     return;
4907   }
4908 
4909   // First, demultiplex/decode time arguments
4910   timespec absTime;
4911   if (time < 0 || (isAbsolute && time == 0)) { // don't wait at all
4912     return;
4913   }
4914   if (time > 0) {
4915     // Warning: this code might be exposed to the old Solaris time
4916     // round-down bugs.  Grep "roundingFix" for details.
4917     unpackTime(&absTime, isAbsolute, time);
4918   }
4919 


< prev index next >