Consistently handle EINTR on FUTEX_WAIT
Change-Id: I848f33b51f7087232275a125d7ae414909233437
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 3265a13..1a6020b 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -172,7 +172,9 @@
}
}
-void BaseMutex::RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t milli_time_blocked) {
+void BaseMutex::RecordContention(uint64_t blocked_tid,
+ uint64_t owner_tid,
+ uint64_t milli_time_blocked) {
#if CONTENTION_LOGGING
++contention_count_;
wait_time_ += static_cast<uint32_t>(milli_time_blocked); // May overflow.
@@ -201,7 +203,8 @@
if (contention_count == 0) {
os << "never contended";
} else {
- os << "contended " << contention_count << " times, average wait of contender " << (wait_time / contention_count) << "ms";
+ os << "contended " << contention_count
+ << " times, average wait of contender " << (wait_time / contention_count) << "ms";
SafeMap<uint64_t, size_t> most_common_blocker;
SafeMap<uint64_t, size_t> most_common_blocked;
typedef SafeMap<uint64_t, size_t>::const_iterator It;
@@ -314,7 +317,9 @@
ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
android_atomic_inc(&num_contenders_);
if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
- if (errno != EAGAIN) {
+ // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
+ // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
+ if ((errno != EAGAIN) && (errno != EINTR)) {
PLOG(FATAL) << "futex wait failed for " << name_;
}
}
@@ -515,7 +520,9 @@
ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
android_atomic_inc(&num_pending_writers_);
if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
- if (errno != EAGAIN) {
+ // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
+ // We don't use TEMP_FAILURE_RETRY so we can intentionally retry to acquire the lock.
+ if ((errno != EAGAIN) && (errno != EINTR)) {
PLOG(FATAL) << "futex wait failed for " << name_;
}
}
@@ -585,7 +592,10 @@
if (errno == ETIMEDOUT) {
android_atomic_dec(&num_pending_writers_);
return false; // Timed out.
- } else if (errno != EAGAIN && errno != EINTR) {
+ } else if ((errno != EAGAIN) && (errno != EINTR)) {
+ // 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;
PLOG(FATAL) << "timed futex wait failed for " << name_;
}
}
@@ -838,7 +848,7 @@
if (futex(&sequence_, FUTEX_WAIT, cur_sequence, &rel_ts, NULL, 0) != 0) {
if (errno == ETIMEDOUT) {
// Timed out we're done.
- } else if ((errno == EINTR) || (errno == EAGAIN)) {
+ } else if ((errno == EAGAIN) || (errno == EINTR)) {
// A signal or ConditionVariable::Signal/Broadcast has come in.
} else {
PLOG(FATAL) << "timed futex wait failed for " << name_;