tsan: add dynamic library target for standalone deadlock detector

it's LD_PRELOAD-able

llvm-svn: 202843
This commit is contained in:
Dmitry Vyukov 2014-03-04 12:52:20 +00:00
parent 4b6845c7e7
commit d1d8653742
8 changed files with 176 additions and 4 deletions

View File

@ -6,6 +6,7 @@ set(SANITIZER_SOURCES
sanitizer_common.cc
sanitizer_coverage.cc
sanitizer_deadlock_detector1.cc
sanitizer_deadlock_detector2.cc
sanitizer_flags.cc
sanitizer_libc.cc
sanitizer_libignore.cc

View File

@ -17,6 +17,8 @@
#include "sanitizer_placement_new.h"
#include "sanitizer_mutex.h"
#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
namespace __sanitizer {
typedef TwoLevelBitVector<> DDBV; // DeadlockDetector's bit vector.
@ -142,3 +144,4 @@ void DDetectorImpl::MutexDestroy(DDPhysicalThread *pt, DDLogicalThread *lt,
}
} // namespace __sanitizer
#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1

View File

@ -0,0 +1,139 @@
//===-- sanitizer_deadlock_detector1.cc -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Deadlock detector implementation based on NxN adjacency bit matrix.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_deadlock_detector_interface.h"
#include "sanitizer_allocator_internal.h"
#include "sanitizer_placement_new.h"
//#include "sanitizer_mutex.h"
#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
namespace __sanitizer {
struct DDPhysicalThread {
DDReport rep;
};
struct DDLogicalThread {
u64 ctx;
};
struct DDetectorImpl : public DDetector {
DDetectorImpl();
virtual DDPhysicalThread* CreatePhysicalThread();
virtual void DestroyPhysicalThread(DDPhysicalThread *pt);
virtual DDLogicalThread* CreateLogicalThread(u64 ctx);
virtual void DestroyLogicalThread(DDLogicalThread *lt);
virtual void MutexInit(DDMutex *m, u32 stk, u64 ctx);
virtual DDReport *MutexLock(DDPhysicalThread *pt, DDLogicalThread *lt,
DDMutex *m, bool writelock, bool trylock);
virtual DDReport *MutexUnlock(DDPhysicalThread *pt, DDLogicalThread *lt,
DDMutex *m, bool writelock);
virtual void MutexDestroy(DDPhysicalThread *pt, DDLogicalThread *lt,
DDMutex *m);
};
DDetector *DDetector::Create() {
void *mem = MmapOrDie(sizeof(DDetectorImpl), "deadlock detector");
return new(mem) DDetectorImpl();
}
DDetectorImpl::DDetectorImpl() {
}
DDPhysicalThread* DDetectorImpl::CreatePhysicalThread() {
void *mem = InternalAlloc(sizeof(DDPhysicalThread));
DDPhysicalThread *pt = new(mem) DDPhysicalThread();
return pt;
}
void DDetectorImpl::DestroyPhysicalThread(DDPhysicalThread *pt) {
pt->~DDPhysicalThread();
InternalFree(pt);
}
DDLogicalThread* DDetectorImpl::CreateLogicalThread(u64 ctx) {
void *mem = InternalAlloc(sizeof(
DDLogicalThread));
DDLogicalThread *lt = new(mem) DDLogicalThread();
lt->ctx = ctx;
return lt;
}
void DDetectorImpl::DestroyLogicalThread(DDLogicalThread *lt) {
lt->~DDLogicalThread();
InternalFree(lt);
}
void DDetectorImpl::MutexInit(DDMutex *m, u32 stk, u64 ctx) {
m->id = 0;
m->stk = stk;
m->ctx = ctx;
}
DDReport *DDetectorImpl::MutexLock(DDPhysicalThread *pt, DDLogicalThread *lt,
DDMutex *m, bool writelock, bool trylock) {
/*
if (dd.onFirstLock(&lt->dd, m->id))
return 0;
SpinMutexLock lk(&mtx);
MutexEnsureID(lt, m);
CHECK(!dd.isHeld(&lt->dd, m->id));
// Printf("T%d MutexLock: %zx\n", thr->tid, s->deadlock_detector_id);
bool has_deadlock = trylock
? dd.onTryLock(&lt->dd, m->id)
: dd.onLock(&lt->dd, m->id);
DDReport *rep = 0;
if (has_deadlock) {
uptr path[10];
uptr len = dd.findPathToHeldLock(&lt->dd, m->id,
path, ARRAY_SIZE(path));
CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that.
rep = &lt->rep;
rep->n = len;
for (uptr i = 0; i < len; i++) {
DDMutex *m0 = (DDMutex*)dd.getData(path[i]);
DDMutex *m1 = (DDMutex*)dd.getData(path[i < len - 1 ? i + 1 : 0]);
rep->loop[i].thr_ctx = 0; // don't know
rep->loop[i].mtx_ctx0 = m0->ctx;
rep->loop[i].mtx_ctx1 = m1->ctx;
rep->loop[i].stk = m0->stk;
}
}
return rep;
*/
return 0;
}
DDReport *DDetectorImpl::MutexUnlock(DDPhysicalThread *pt, DDLogicalThread *lt,
DDMutex *m, bool writelock) {
//dd.onUnlock(&lt->dd, m->id);
return 0;
}
void DDetectorImpl::MutexDestroy(DDPhysicalThread *pt, DDLogicalThread *lt,
DDMutex *m) {
/*
if (!m->id) return;
SpinMutexLock lk(&mtx);
if (dd.nodeBelongsToCurrentEpoch(m->id))
dd.removeNode(m->id);
m->id = 0;
*/
}
} // namespace __sanitizer
#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2

View File

@ -16,6 +16,8 @@
#ifndef SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
#define SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
#define SANITIZER_DEADLOCK_DETECTOR_VERSION 1
#include "sanitizer_internal_defs.h"
namespace __sanitizer {

View File

@ -11,6 +11,8 @@ else()
set(DD_COMMON_DEFINITIONS DEBUG=1)
endif()
set(DD_DYNAMIC_DEFINITIONS DYNAMIC=1)
set(DD_SOURCES
dd_rtl.cc
dd_interceptors.cc
@ -22,7 +24,7 @@ set(DD_HEADERS
add_custom_target(dd)
# Deadlock detector is currently supported on 64-bit Linux only.
if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE)
if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE AND NOT ANDROID)
set(arch "x86_64")
add_compiler_rt_static_runtime(clang_rt.dd-${arch} ${arch}
SOURCES ${DD_SOURCES}
@ -31,6 +33,23 @@ if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE)
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
CFLAGS ${DD_CFLAGS}
DEFS ${DD_COMMON_DEFINITIONS})
add_library(RTDD OBJECT ${DD_SOURCES})
set_target_compile_flags(RTDD ${DD_CFLAGS})
set_property(TARGET RTDD APPEND PROPERTY
COMPILE_DEFINITIONS ${DD_COMMON_DEFINITIONS})
set_property(TARGET RTDD APPEND PROPERTY
COMPILE_DEFINITIONS ${DD_DYNAMIC_DEFINITIONS})
add_library(clang_rt.dyndd-${arch} SHARED
$<TARGET_OBJECTS:RTDD>
$<TARGET_OBJECTS:RTInterception.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
# set_target_compile_flags(clang_rt.dd-${arch} ${DD_CFLAGS})
# set_property(TARGET clang_rt.dd-${arch} APPEND PROPERTY
# COMPILE_DEFINITIONS ${DD_COMMON_DEFINITIONS})
target_link_libraries(clang_rt.dyndd-${arch} pthread dl)
endif()
add_dependencies(compiler-rt dd)

View File

@ -66,3 +66,13 @@ void InitializeInterceptors() {
}
} // namespace __dsan
#if DYNAMIC
static void __local_dsan_init() __attribute__((constructor));
void __local_dsan_init() {
__dsan::Initialize();
}
#else
__attribute__((section(".preinit_array"), used))
void (*__local_dsan_preinit)(void) = __dsan::Initialize;
#endif

View File

@ -100,6 +100,3 @@ void MutexDestroy(Thread *thr, uptr m) {
}
} // namespace __dsan
__attribute__((section(".preinit_array"), used))
void (*__local_dsan_preinit)(void) = __dsan::Initialize;

View File

@ -36,6 +36,7 @@ struct Context {
MutexHashMap mutex_map;
};
void Initialize();
void InitializeInterceptors();
void ThreadInit(Thread *thr);