aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/tests/standalone_malloc_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/tests/standalone_malloc_test.cc')
-rw-r--r--lib/sanitizer_common/tests/standalone_malloc_test.cc87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/sanitizer_common/tests/standalone_malloc_test.cc b/lib/sanitizer_common/tests/standalone_malloc_test.cc
new file mode 100644
index 000000000000..9e6f7c93b04b
--- /dev/null
+++ b/lib/sanitizer_common/tests/standalone_malloc_test.cc
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <vector>
+#include <pthread.h>
+#include <malloc.h>
+#include <algorithm>
+
+using namespace std;
+
+const size_t kNumThreds = 16;
+const size_t kNumIters = 1 << 23;
+
+inline void break_optimization(void *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+}
+
+__attribute__((noinline))
+static void *MallocThread(void *t) {
+ size_t total_malloced = 0, total_freed = 0;
+ size_t max_in_use = 0;
+ size_t tid = reinterpret_cast<size_t>(t);
+ vector<pair<char *, size_t> > allocated;
+ allocated.reserve(kNumIters);
+ for (size_t i = 1; i < kNumIters; i++) {
+ if ((i % (kNumIters / 4)) == 0 && tid == 0)
+ fprintf(stderr, " T[%ld] iter %ld\n", tid, i);
+ bool allocate = (i % 5) <= 2; // 60% malloc, 40% free
+ if (i > kNumIters / 4)
+ allocate = i % 2; // then switch to 50% malloc, 50% free
+ if (allocate) {
+ size_t size = 1 + (i % 200);
+ if ((i % 10001) == 0)
+ size *= 4096;
+ total_malloced += size;
+ char *x = new char[size];
+ x[0] = x[size - 1] = x[size / 2] = 0;
+ allocated.push_back(make_pair(x, size));
+ max_in_use = max(max_in_use, total_malloced - total_freed);
+ } else {
+ if (allocated.empty()) continue;
+ size_t slot = i % allocated.size();
+ char *p = allocated[slot].first;
+ p[0] = 0; // emulate last user touch of the block
+ size_t size = allocated[slot].second;
+ total_freed += size;
+ swap(allocated[slot], allocated.back());
+ allocated.pop_back();
+ delete [] p;
+ }
+ }
+ if (tid == 0)
+ fprintf(stderr, " T[%ld] total_malloced: %ldM in use %ldM max %ldM\n",
+ tid, total_malloced >> 20, (total_malloced - total_freed) >> 20,
+ max_in_use >> 20);
+ for (size_t i = 0; i < allocated.size(); i++)
+ delete [] allocated[i].first;
+ return 0;
+}
+
+template <int depth>
+struct DeepStack {
+ __attribute__((noinline))
+ static void *run(void *t) {
+ break_optimization(0);
+ DeepStack<depth - 1>::run(t);
+ break_optimization(0);
+ return 0;
+ }
+};
+
+template<>
+struct DeepStack<0> {
+ static void *run(void *t) {
+ MallocThread(t);
+ return 0;
+ }
+};
+
+// Build with -Dstandalone_malloc_test=main to make it a separate program.
+int standalone_malloc_test() {
+ pthread_t t[kNumThreds];
+ for (size_t i = 0; i < kNumThreds; i++)
+ pthread_create(&t[i], 0, DeepStack<200>::run, reinterpret_cast<void *>(i));
+ for (size_t i = 0; i < kNumThreds; i++)
+ pthread_join(t[i], 0);
+ malloc_stats();
+ return 0;
+}