summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2014-03-19 12:26:33 +0000
committerKostya Serebryany <kcc@google.com>2014-03-19 12:26:33 +0000
commit2ea796e05f586e585f1f62c718245cfed78b0130 (patch)
treed8f7b728620c6681dd344960aca256dbfe7b6c31
parente7e8b26f9381f32bc3fca736390ffe7fd6f0f0f2 (diff)
downloadbcm5719-llvm-2ea796e05f586e585f1f62c718245cfed78b0130.tar.gz
bcm5719-llvm-2ea796e05f586e585f1f62c718245cfed78b0130.zip
[sanitizer] deadlock detector: a) initial support for suppressions, b) be more robust in case we failed to extract a stack trace for one of the locks
llvm-svn: 204225
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h1
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc4
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc16
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_suppressions.cc2
-rw-r--r--compiler-rt/test/tsan/mutex_cycle2.c4
6 files changed, 24 insertions, 7 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
index 5f3d2cee8ce..87ccf7fca22 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -20,8 +20,8 @@
namespace __sanitizer {
static const char *const kTypeStrings[SuppressionTypeCount] = {
- "none", "race", "mutex", "thread", "signal", "leak", "called_from_lib"
-};
+ "none", "race", "mutex", "thread",
+ "signal", "leak", "called_from_lib", "deadlock"};
bool TemplateMatch(char *templ, const char *str) {
if (str == 0 || str[0] == 0)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
index 92cb09365b5..772b9aab5ba 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
@@ -26,6 +26,7 @@ enum SuppressionType {
SuppressionSignal,
SuppressionLeak,
SuppressionLib,
+ SuppressionDeadlock,
SuppressionTypeCount
};
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
index ea8741d4f01..93fc8a35dc8 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
@@ -67,8 +67,10 @@ TEST(Suppressions, TypeStrings) {
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLeak), "leak"));
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLib),
"called_from_lib"));
+ CHECK(
+ !internal_strcmp(SuppressionTypeString(SuppressionDeadlock), "deadlock"));
// Ensure this test is up-to-date when suppression types are added.
- CHECK_EQ(SuppressionTypeCount, 7);
+ CHECK_EQ(SuppressionTypeCount, 8);
}
class SuppressionContextTest : public ::testing::Test {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
index 8398e4b4522..ab083ab2940 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -428,17 +428,25 @@ void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
for (int i = 0; i < r->n; i++)
rep.AddMutex(r->loop[i].mtx_ctx0);
StackTrace stacks[2 * DDReport::kMaxLoopSize];
+ uptr dummy_pc = 0x42;
for (int i = 0; i < r->n; i++) {
uptr size;
for (int j = 0; j < 2; j++) {
u32 stk = r->loop[i].stk[j];
- if (!stk) continue;
- const uptr *trace = StackDepotGet(stk, &size);
- stacks[i].Init(const_cast<uptr *>(trace), size);
+ if (stk) {
+ const uptr *trace = StackDepotGet(stk, &size);
+ stacks[i].Init(const_cast<uptr *>(trace), size);
+ } else {
+ // Sometimes we fail to extract the stack trace (FIXME: investigate),
+ // but we should still produce some stack trace in the report.
+ stacks[i].Init(&dummy_pc, 1);
+ }
rep.AddStack(&stacks[i]);
}
}
- OutputReport(ctx, rep);
+ // FIXME: use all stacks for suppressions, not just the second stack of the
+ // first edge.
+ OutputReport(ctx, rep, rep.GetReport()->stacks[1]);
#endif // TSAN_GO
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
index 4b0ac04c48a..608b7af5f20 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
@@ -107,6 +107,8 @@ SuppressionType conv(ReportType typ) {
return SuppressionSignal;
else if (typ == ReportTypeErrnoInSignal)
return SuppressionNone;
+ else if (typ == ReportTypeDeadlock)
+ return SuppressionDeadlock;
Printf("ThreadSanitizer: unknown report type %d\n", typ),
Die();
}
diff --git a/compiler-rt/test/tsan/mutex_cycle2.c b/compiler-rt/test/tsan/mutex_cycle2.c
index 32bb067567f..bb4c1b04938 100644
--- a/compiler-rt/test/tsan/mutex_cycle2.c
+++ b/compiler-rt/test/tsan/mutex_cycle2.c
@@ -1,5 +1,9 @@
// RUN: %clangxx_tsan %s -o %t
// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
+// RUN: echo "deadlock:main" > sup
+// RUN: TSAN_OPTIONS="detect_deadlocks=1 suppressions=sup" %t
+// RUN: echo "deadlock:zzzz" > sup
+// RUN: TSAN_OPTIONS="detect_deadlocks=1 suppressions=sup" not %t 2>&1 | FileCheck %s
#include <pthread.h>
int main() {
OpenPOWER on IntegriCloud