summaryrefslogtreecommitdiff
path: root/lib/tsan
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-01-24 09:08:03 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-01-24 09:08:03 +0000
commitbdd844cb41718c27ef727a99a236191bc29a3df8 (patch)
tree5ade9022b178bd4c6b130c7a2cc9cb6085d7b56b /lib/tsan
parentf0c846b8ef61a5f4bc664c463d643bb8dedc3768 (diff)
tsan: implement malloc stats querying
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@173332 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r--lib/tsan/rtl/tsan_mman.cc42
-rw-r--r--lib/tsan/rtl/tsan_mman.h4
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc5
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc5
-rw-r--r--lib/tsan/tests/unit/tsan_mman_test.cc39
5 files changed, 83 insertions, 12 deletions
diff --git a/lib/tsan/rtl/tsan_mman.cc b/lib/tsan/rtl/tsan_mman.cc
index 6f8e90d62..314e20f63 100644
--- a/lib/tsan/rtl/tsan_mman.cc
+++ b/lib/tsan/rtl/tsan_mman.cc
@@ -38,8 +38,16 @@ void InitializeAllocator() {
allocator()->Init();
}
-void AlloctorThreadFinish(ThreadState *thr) {
- allocator()->SwallowCache(&thr->alloc_cache);
+void AllocatorThreadStart(ThreadState *thr) {
+ allocator()->InitCache(&thr->alloc_cache);
+}
+
+void AllocatorThreadFinish(ThreadState *thr) {
+ allocator()->DestroyCache(&thr->alloc_cache);
+}
+
+void AllocatorPrintStats() {
+ allocator()->PrintStats();
}
static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
@@ -169,30 +177,44 @@ using namespace __tsan;
extern "C" {
uptr __tsan_get_current_allocated_bytes() {
- return 0;
+ u64 stats[AllocatorStatCount];
+ allocator()->GetStats(stats);
+ u64 m = stats[AllocatorStatMalloced];
+ u64 f = stats[AllocatorStatFreed];
+ return m >= f ? m - f : 1;
}
uptr __tsan_get_heap_size() {
- return 1;
+ u64 stats[AllocatorStatCount];
+ allocator()->GetStats(stats);
+ u64 m = stats[AllocatorStatMmapped];
+ u64 f = stats[AllocatorStatUnmapped];
+ return m >= f ? m - f : 1;
}
uptr __tsan_get_free_bytes() {
- return 1;
+ return 0;
}
uptr __tsan_get_unmapped_bytes() {
- return 1;
+ return 0;
}
uptr __tsan_get_estimated_allocated_size(uptr size) {
return size;
}
-bool __tsan_get_ownership(const void *p) {
- return true;
+bool __tsan_get_ownership(void *p) {
+ return allocator()->GetBlockBegin(p) != 0;
}
-uptr __tsan_get_allocated_size(const void *p) {
- return 0;
+uptr __tsan_get_allocated_size(void *p) {
+ if (p == 0)
+ return 0;
+ p = allocator()->GetBlockBegin(p);
+ if (p == 0)
+ return 0;
+ MBlock *b = (MBlock*)allocator()->GetMetaData(p);
+ return b->size;
}
} // extern "C"
diff --git a/lib/tsan/rtl/tsan_mman.h b/lib/tsan/rtl/tsan_mman.h
index 5cf00eac8..dc31acd75 100644
--- a/lib/tsan/rtl/tsan_mman.h
+++ b/lib/tsan/rtl/tsan_mman.h
@@ -20,7 +20,9 @@ namespace __tsan {
const uptr kDefaultAlignment = 16;
void InitializeAllocator();
-void AlloctorThreadFinish(ThreadState *thr);
+void AllocatorThreadStart(ThreadState *thr);
+void AllocatorThreadFinish(ThreadState *thr);
+void AllocatorPrintStats();
// For user allocations.
void *user_alloc(ThreadState *thr, uptr pc, uptr sz,
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index 493ed2055..17a2e2d73 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -255,6 +255,11 @@ int Finalize(ThreadState *thr) {
ctx->report_mtx.Lock();
ctx->report_mtx.Unlock();
+#ifndef TSAN_GO
+ if (ctx->flags.verbosity)
+ AllocatorPrintStats();
+#endif
+
ThreadFinalize(thr);
if (ctx->nreported) {
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index 359775927..0c74d57e3 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -209,6 +209,9 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
thr->shadow_stack_pos = thr->shadow_stack;
thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
#endif
+#ifndef TSAN_GO
+ AllocatorThreadStart(thr);
+#endif
tctx->thr = thr;
thr->fast_synch_epoch = tctx->epoch0;
thr->clock.set(tid, tctx->epoch0);
@@ -269,7 +272,7 @@ void ThreadFinish(ThreadState *thr) {
tctx->epoch1 = thr->fast_state.epoch();
#ifndef TSAN_GO
- AlloctorThreadFinish(thr);
+ AllocatorThreadFinish(thr);
#endif
thr->~ThreadState();
StatAggregate(ctx->stat, thr->stat);
diff --git a/lib/tsan/tests/unit/tsan_mman_test.cc b/lib/tsan/tests/unit/tsan_mman_test.cc
index 1a9a88f60..988918fff 100644
--- a/lib/tsan/tests/unit/tsan_mman_test.cc
+++ b/lib/tsan/tests/unit/tsan_mman_test.cc
@@ -14,6 +14,16 @@
#include "tsan_rtl.h"
#include "gtest/gtest.h"
+extern "C" {
+uptr __tsan_get_current_allocated_bytes();
+uptr __tsan_get_heap_size();
+uptr __tsan_get_free_bytes();
+uptr __tsan_get_unmapped_bytes();
+uptr __tsan_get_estimated_allocated_size(uptr size);
+bool __tsan_get_ownership(void *p);
+uptr __tsan_get_allocated_size(void *p);
+}
+
namespace __tsan {
TEST(Mman, Internal) {
@@ -106,4 +116,33 @@ TEST(Mman, UserRealloc) {
}
}
+TEST(Mman, Stats) {
+ ScopedInRtl in_rtl;
+ ThreadState *thr = cur_thread();
+
+ uptr alloc0 = __tsan_get_current_allocated_bytes();
+ uptr heap0 = __tsan_get_heap_size();
+ uptr free0 = __tsan_get_free_bytes();
+ uptr unmapped0 = __tsan_get_unmapped_bytes();
+
+ EXPECT_EQ(__tsan_get_estimated_allocated_size(10), (uptr)10);
+ EXPECT_EQ(__tsan_get_estimated_allocated_size(20), (uptr)20);
+ EXPECT_EQ(__tsan_get_estimated_allocated_size(100), (uptr)100);
+
+ char *p = (char*)user_alloc(thr, 0, 10);
+ EXPECT_EQ(__tsan_get_ownership(p), true);
+ EXPECT_EQ(__tsan_get_allocated_size(p), (uptr)10);
+
+ EXPECT_EQ(__tsan_get_current_allocated_bytes(), alloc0 + 16);
+ EXPECT_GE(__tsan_get_heap_size(), heap0);
+ EXPECT_EQ(__tsan_get_free_bytes(), free0);
+ EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
+
+ user_free(thr, 0, p);
+
+ EXPECT_EQ(__tsan_get_current_allocated_bytes(), alloc0);
+ EXPECT_GE(__tsan_get_heap_size(), heap0);
+ EXPECT_EQ(__tsan_get_free_bytes(), free0);
+ EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
+}
} // namespace __tsan