summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--absl/hash/internal/hash.h3
-rw-r--r--absl/strings/cord_buffer.h2
-rw-r--r--absl/synchronization/mutex.cc5
-rw-r--r--absl/synchronization/mutex_test.cc19
-rw-r--r--absl/types/optional_test.cc15
5 files changed, 32 insertions, 12 deletions
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 89740dab..61970e0d 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -1074,6 +1074,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
// Reads 1 to 3 bytes from p. Zero pads to fill uint32_t.
static uint32_t Read1To3(const unsigned char* p, size_t len) {
+ // The trick used by this implementation is to avoid branches if possible.
unsigned char mem0 = p[0];
unsigned char mem1 = p[len / 2];
unsigned char mem2 = p[len - 1];
@@ -1083,7 +1084,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
unsigned char significant0 = mem0;
#else
unsigned char significant2 = mem0;
- unsigned char significant1 = mem1;
+ unsigned char significant1 = len == 2 ? mem0 : mem1;
unsigned char significant0 = mem2;
#endif
return static_cast<uint32_t>(significant0 | //
diff --git a/absl/strings/cord_buffer.h b/absl/strings/cord_buffer.h
index e39c84cd..a3600ac4 100644
--- a/absl/strings/cord_buffer.h
+++ b/absl/strings/cord_buffer.h
@@ -460,7 +460,7 @@ inline constexpr size_t CordBuffer::MaximumPayload() {
}
inline constexpr size_t CordBuffer::MaximumPayload(size_t block_size) {
- return std::min(kCustomLimit, block_size) - cord_internal::kFlatOverhead;
+ return (std::min)(kCustomLimit, block_size) - cord_internal::kFlatOverhead;
}
inline CordBuffer CordBuffer::CreateWithDefaultLimit(size_t capacity) {
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index f6a8506c..a8911614 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -1403,7 +1403,7 @@ static GraphId DeadlockCheck(Mutex *mu) {
ABSL_RAW_LOG(ERROR, "Cycle: ");
int path_len = deadlock_graph->FindPath(
mu_id, other_node_id, ABSL_ARRAYSIZE(b->path), b->path);
- for (int j = 0; j != path_len; j++) {
+ for (int j = 0; j != path_len && j != ABSL_ARRAYSIZE(b->path); j++) {
GraphId id = b->path[j];
Mutex *path_mu = static_cast<Mutex *>(deadlock_graph->Ptr(id));
if (path_mu == nullptr) continue;
@@ -1416,6 +1416,9 @@ static GraphId DeadlockCheck(Mutex *mu) {
symbolize);
ABSL_RAW_LOG(ERROR, "%s", b->buf);
}
+ if (path_len > static_cast<int>(ABSL_ARRAYSIZE(b->path))) {
+ ABSL_RAW_LOG(ERROR, "(long cycle; list truncated)");
+ }
if (synch_deadlock_detection.load(std::memory_order_acquire) ==
OnDeadlockCycle::kAbort) {
deadlock_graph_mu.Unlock(); // avoid deadlock in fatal sighandler
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index 34751cb1..f76b1e8b 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -1131,6 +1131,25 @@ TEST(Mutex, DeadlockDetectorBazelWarning) {
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
}
+TEST(Mutex, DeadlockDetectorLongCycle) {
+ absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);
+
+ // This test generates a warning if it passes, and crashes otherwise.
+ // Cause bazel to ignore the warning.
+ ScopedDisableBazelTestWarnings disable_bazel_test_warnings;
+
+ // Check that we survive a deadlock with a lock cycle.
+ std::vector<absl::Mutex> mutex(100);
+ for (size_t i = 0; i != mutex.size(); i++) {
+ mutex[i].Lock();
+ mutex[(i + 1) % mutex.size()].Lock();
+ mutex[i].Unlock();
+ mutex[(i + 1) % mutex.size()].Unlock();
+ }
+
+ absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
+}
+
// This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the
// annotation-based static thread-safety analysis is not currently
// predicate-aware and cannot tell if the two for-loops that acquire and
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index fbd4e8c2..83a9bb4a 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -97,9 +97,9 @@ struct StructorListener {
// 4522: multiple assignment operators specified
// We wrote multiple of them to test that the correct overloads are selected.
#ifdef _MSC_VER
-#pragma warning( push )
-#pragma warning( disable : 4521)
-#pragma warning( disable : 4522)
+#pragma warning(push)
+#pragma warning(disable : 4521)
+#pragma warning(disable : 4522)
#endif
struct Listenable {
static StructorListener* listener;
@@ -133,7 +133,7 @@ struct Listenable {
~Listenable() { ++listener->destruct; }
};
#ifdef _MSC_VER
-#pragma warning( pop )
+#pragma warning(pop)
#endif
StructorListener* Listenable::listener = nullptr;
@@ -987,9 +987,8 @@ TEST(optionalTest, PointerStuff) {
// Skip that test to make the build green again when using the old compiler.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59296 is fixed in 4.9.1.
#if defined(__GNUC__) && !defined(__clang__)
-#define GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
+#define GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40901
#define ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG
#endif
@@ -1201,7 +1200,6 @@ void optionalTest_Comparisons_EXPECT_GREATER(T x, U y) {
EXPECT_TRUE(x >= y);
}
-
template <typename T, typename U, typename V>
void TestComparisons() {
absl::optional<T> ae, a2{2}, a4{4};
@@ -1294,7 +1292,6 @@ TEST(optionalTest, Comparisons) {
EXPECT_TRUE(e1 == e2);
}
-
TEST(optionalTest, SwapRegression) {
StructorListener listener;
Listenable::listener = &listener;