diff options
Diffstat (limited to 'runtime/base/mutex.cc')
| -rw-r--r-- | runtime/base/mutex.cc | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc index 5709333756..728dc842c2 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -28,6 +28,7 @@ #include "base/systrace.h" #include "base/time_utils.h" #include "base/value_object.h" +#include "monitor.h" #include "mutex-inl.h" #include "scoped_thread_state_change-inl.h" #include "thread-inl.h" @@ -59,18 +60,19 @@ struct DumpStackLastTimeTLSData : public art::TLSData { }; #if ART_USE_FUTEXES +// Compute a relative timespec as *result_ts = lhs - rhs. +// Return false (and produce an invalid *result_ts) if lhs < rhs. static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) { const int32_t one_sec = 1000 * 1000 * 1000; // one second in nanoseconds. + static_assert(std::is_signed<decltype(result_ts->tv_sec)>::value); // Signed on Linux. result_ts->tv_sec = lhs.tv_sec - rhs.tv_sec; result_ts->tv_nsec = lhs.tv_nsec - rhs.tv_nsec; if (result_ts->tv_nsec < 0) { result_ts->tv_sec--; result_ts->tv_nsec += one_sec; - } else if (result_ts->tv_nsec > one_sec) { - result_ts->tv_sec++; - result_ts->tv_nsec -= one_sec; } - return result_ts->tv_sec < 0; + DCHECK(result_ts->tv_nsec >= 0 && result_ts->tv_nsec < one_sec); + return result_ts->tv_sec >= 0; } #endif @@ -462,7 +464,10 @@ void Mutex::ExclusiveLock(Thread* self) { do { timespec timeout_ts; timeout_ts.tv_sec = 0; - timeout_ts.tv_nsec = Runtime::Current()->GetMonitorTimeoutNs(); + // NB: Some tests use the mutex without the runtime. + timeout_ts.tv_nsec = Runtime::Current() != nullptr + ? Runtime::Current()->GetMonitorTimeoutNs() + : Monitor::kDefaultMonitorTimeoutMs; if (futex(state_and_contenders_.Address(), FUTEX_WAIT_PRIVATE, cur_state, enable_monitor_timeout_ ? &timeout_ts : nullptr , nullptr, 0) != 0) { // We only went to sleep after incrementing and contenders and checking that the @@ -512,6 +517,7 @@ void Mutex::DumpStack(Thread* self, uint64_t wait_start_ms, uint64_t try_times) Locks::thread_list_lock_->ExclusiveLock(self); std::string owner_stack_dump; pid_t owner_tid = GetExclusiveOwnerTid(); + CHECK(Runtime::Current() != nullptr); Thread *owner = Runtime::Current()->GetThreadList()->FindThreadByTid(owner_tid); if (owner != nullptr) { if (IsDumpFrequent(owner, try_times)) { @@ -852,7 +858,7 @@ bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32 timespec now_abs_ts; InitTimeSpec(true, CLOCK_MONOTONIC, 0, 0, &now_abs_ts); timespec rel_ts; - if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) { + if (!ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) { return false; // Timed out. } ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid()); @@ -869,6 +875,7 @@ bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32 // EAGAIN and EINTR both indicate a spurious failure, // recompute the relative time out from now and try again. // We don't use TEMP_FAILURE_RETRY so we can recompute rel_ts; + num_contenders_.fetch_sub(1); // Unlikely to matter. PLOG(FATAL) << "timed futex wait failed for " << name_; } } |