summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2016-07-20 13:43:47 +0000
committerHans Wennborg <hans@hanshq.net>2016-07-20 13:43:47 +0000
commit95277fbc5a050588234bc4e2a52d7902e663e3b1 (patch)
tree4a274d815decb265f39185d319176fff58b60b7b
parentc10168c3b09f714b9da56abcce1b48104c20e1f9 (diff)
downloadcompiler-rt-95277fbc5a050588234bc4e2a52d7902e663e3b1.tar.gz
Merging r275946 and r275948:
------------------------------------------------------------------------ r275946 | bruening | 2016-07-18 22:03:38 -0700 (Mon, 18 Jul 2016) | 5 lines [esan] Fix sideline thread flaky assert Fixes an esan sideline thread CHECK that failed to account for the sideline thread reaching its code before the internal_clone() return value was assigned in the parent. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r275948 | bruening | 2016-07-18 22:06:48 -0700 (Mon, 18 Jul 2016) | 4 lines [esan|wset] Fix flaky sampling tests Adds a new esan public interface routine __esan_get_sample_count() and uses it to ensure that tests of sampling receive the minimum number of samples. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/branches/release_39@276114 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/sanitizer/esan_interface.h4
-rw-r--r--lib/esan/esan.cpp8
-rw-r--r--lib/esan/esan.h1
-rw-r--r--lib/esan/esan_interface.cpp4
-rw-r--r--lib/esan/esan_sideline_linux.cpp9
-rw-r--r--lib/esan/working_set.cpp5
-rw-r--r--lib/esan/working_set.h1
-rw-r--r--test/esan/TestCases/workingset-midreport.cpp18
-rw-r--r--test/esan/TestCases/workingset-samples.cpp19
9 files changed, 50 insertions, 19 deletions
diff --git a/include/sanitizer/esan_interface.h b/include/sanitizer/esan_interface.h
index 31e9b9b4d..4aff8d47b 100644
--- a/include/sanitizer/esan_interface.h
+++ b/include/sanitizer/esan_interface.h
@@ -39,6 +39,10 @@ extern "C" {
// data for that point in the run be reported from the tool.
void COMPILER_RT_WEAK __esan_report();
+// This function returns the number of samples that the esan tool has collected
+// to this point. This is useful for testing.
+unsigned int COMPILER_RT_WEAK __esan_get_sample_count();
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/lib/esan/esan.cpp b/lib/esan/esan.cpp
index 3c69b4e91..2fb77894d 100644
--- a/lib/esan/esan.cpp
+++ b/lib/esan/esan.cpp
@@ -259,4 +259,12 @@ void processCompilationUnitExit(void *Ptr) {
}
}
+unsigned int getSampleCount() {
+ VPrintf(1, "in esan::%s\n", __FUNCTION__);
+ if (__esan_which_tool == ESAN_WorkingSet) {
+ return getSampleCountWorkingSet();
+ }
+ return 0;
+}
+
} // namespace __esan
diff --git a/lib/esan/esan.h b/lib/esan/esan.h
index 371810d5e..5a0dde627 100644
--- a/lib/esan/esan.h
+++ b/lib/esan/esan.h
@@ -38,6 +38,7 @@ extern bool EsanDuringInit;
void initializeLibrary(ToolType Tool);
int finalizeLibrary();
void reportResults();
+unsigned int getSampleCount();
// Esan creates the variable per tool per compilation unit at compile time
// and passes its pointer Ptr to the runtime library.
void processCompilationUnitInit(void *Ptr);
diff --git a/lib/esan/esan_interface.cpp b/lib/esan/esan_interface.cpp
index 8a64d1526..43b3dff86 100644
--- a/lib/esan/esan_interface.cpp
+++ b/lib/esan/esan_interface.cpp
@@ -115,4 +115,8 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __esan_report() {
reportResults();
}
+
+SANITIZER_INTERFACE_ATTRIBUTE unsigned int __esan_get_sample_count() {
+ return getSampleCount();
+}
} // extern "C"
diff --git a/lib/esan/esan_sideline_linux.cpp b/lib/esan/esan_sideline_linux.cpp
index ba4fe62f5..d04f5909d 100644
--- a/lib/esan/esan_sideline_linux.cpp
+++ b/lib/esan/esan_sideline_linux.cpp
@@ -31,6 +31,7 @@ namespace __esan {
static const int SigAltStackSize = 4*1024;
static const int SidelineStackSize = 4*1024;
+static const uptr SidelineIdUninitialized = 1;
// FIXME: we'll need some kind of TLS (can we trust that a pthread key will
// work in our non-POSIX thread?) to access our data in our signal handler
@@ -113,6 +114,10 @@ bool SidelineThread::launchThread(SidelineFunc takeSample, void *Arg,
// We do without a guard page.
Stack = static_cast<char*>(MmapOrDie(SidelineStackSize, "SidelineStack"));
+ // We need to handle the return value from internal_clone() not having been
+ // assigned yet (for our CHECK in adjustTimer()) so we ensure this has a
+ // sentinel value.
+ SidelineId = SidelineIdUninitialized;
// By omitting CLONE_THREAD, the child is in its own thread group and will not
// receive any of the application's signals.
SidelineId = internal_clone(
@@ -151,7 +156,9 @@ bool SidelineThread::joinThread() {
// Must be called from the sideline thread itself.
bool SidelineThread::adjustTimer(u32 FreqMilliSec) {
- CHECK(internal_getpid() == SidelineId);
+ // The return value of internal_clone() may not have been assigned yet:
+ CHECK(internal_getpid() == SidelineId ||
+ SidelineId == SidelineIdUninitialized);
Freq = FreqMilliSec;
struct itimerval TimerVal;
TimerVal.it_interval.tv_sec = (time_t) Freq / 1000;
diff --git a/lib/esan/working_set.cpp b/lib/esan/working_set.cpp
index 3fde5a8b5..f39111993 100644
--- a/lib/esan/working_set.cpp
+++ b/lib/esan/working_set.cpp
@@ -190,6 +190,11 @@ static void takeSample(void *Arg) {
}
}
+unsigned int getSampleCountWorkingSet()
+{
+ return SnapshotNum;
+}
+
// Initialization that must be done before any instrumented code is executed.
void initializeShadowWorkingSet() {
CHECK(getFlags()->cache_line_size == CacheLineSize);
diff --git a/lib/esan/working_set.h b/lib/esan/working_set.h
index 38ff0635d..6a976c3f9 100644
--- a/lib/esan/working_set.h
+++ b/lib/esan/working_set.h
@@ -24,6 +24,7 @@ void initializeWorkingSet();
void initializeShadowWorkingSet();
int finalizeWorkingSet();
void reportWorkingSet();
+unsigned int getSampleCountWorkingSet();
void processRangeAccessWorkingSet(uptr PC, uptr Addr, SIZE_T Size,
bool IsWrite);
diff --git a/test/esan/TestCases/workingset-midreport.cpp b/test/esan/TestCases/workingset-midreport.cpp
index 470e33ca3..2c29cf48c 100644
--- a/test/esan/TestCases/workingset-midreport.cpp
+++ b/test/esan/TestCases/workingset-midreport.cpp
@@ -17,15 +17,15 @@ const int iters = 6;
int main(int argc, char **argv) {
char *buf = (char *)mmap(0, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- // Try to increase the probability that the sideline thread is
- // scheduled. Unfortunately we can't do proper synchronization
- // without some form of annotation or something.
- sched_yield();
- // Do enough work to get at least 4 samples.
- for (int j = 0; j < iters; ++j) {
- for (int i = 0; i < size; ++i)
- buf[i] = i;
- sched_yield();
+ // To avoid flakiness stemming from whether the sideline thread
+ // is scheduled enough on a loaded test machine, we coordinate
+ // with esan itself:
+ if (__esan_get_sample_count) {
+ while (__esan_get_sample_count() < 4) {
+ for (int i = 0; i < size; ++i)
+ buf[i] = i;
+ sched_yield();
+ }
}
// Ensure a non-esan build works without ifdefs:
if (__esan_report) {
diff --git a/test/esan/TestCases/workingset-samples.cpp b/test/esan/TestCases/workingset-samples.cpp
index 09efcd44f..cf198d2f3 100644
--- a/test/esan/TestCases/workingset-samples.cpp
+++ b/test/esan/TestCases/workingset-samples.cpp
@@ -1,6 +1,7 @@
// RUN: %clang_esan_wset -O0 %s -o %t 2>&1
// RUN: %run %t 2>&1 | FileCheck %s
+#include <sanitizer/esan_interface.h>
#include <sched.h>
#include <stdlib.h>
#include <string.h>
@@ -12,15 +13,15 @@ const int iters = 6;
int main(int argc, char **argv) {
char *buf = (char *)mmap(0, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- // Try to increase the probability that the sideline thread is
- // scheduled. Unfortunately we can't do proper synchronization
- // without some form of annotation or something.
- sched_yield();
- // Do enough work to get at least 4 samples.
- for (int j = 0; j < iters; ++j) {
- for (int i = 0; i < size; ++i)
- buf[i] = i;
- sched_yield();
+ // To avoid flakiness stemming from whether the sideline thread
+ // is scheduled enough on a loaded test machine, we coordinate
+ // with esan itself:
+ if (__esan_get_sample_count) {
+ while (__esan_get_sample_count() < 4) {
+ for (int i = 0; i < size; ++i)
+ buf[i] = i;
+ sched_yield();
+ }
}
munmap(buf, size);
// We only check for a few samples here to reduce the chance of flakiness.