[esan|wset] Fix flaky sampling tests
authorDerek Bruening <bruening@google.com>
Tue, 19 Jul 2016 05:06:48 +0000 (05:06 +0000)
committerDerek Bruening <bruening@google.com>
Tue, 19 Jul 2016 05:06:48 +0000 (05:06 +0000)
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.

llvm-svn: 275948

compiler-rt/include/sanitizer/esan_interface.h
compiler-rt/lib/esan/esan.cpp
compiler-rt/lib/esan/esan.h
compiler-rt/lib/esan/esan_interface.cpp
compiler-rt/lib/esan/working_set.cpp
compiler-rt/lib/esan/working_set.h
compiler-rt/test/esan/TestCases/workingset-midreport.cpp
compiler-rt/test/esan/TestCases/workingset-samples.cpp

index 31e9b9b..4aff8d4 100644 (file)
@@ -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
index 3c69b4e..2fb7789 100644 (file)
@@ -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
index 371810d..5a0dde6 100644 (file)
@@ -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);
index 8a64d15..43b3dff 100644 (file)
@@ -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"
index 3fde5a8..f391119 100644 (file)
@@ -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);
index 38ff063..6a976c3 100644 (file)
@@ -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);
 
index 470e33c..2c29cf4 100644 (file)
@@ -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) {
index 09efcd4..cf198d2 100644 (file)
@@ -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.