forked from OSchip/llvm-project
tsan: add dynamic library target for standalone deadlock detector
it's LD_PRELOAD-able llvm-svn: 202843
This commit is contained in:
parent
4b6845c7e7
commit
d1d8653742
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(<->dd, m->id))
|
||||
return 0;
|
||||
SpinMutexLock lk(&mtx);
|
||||
MutexEnsureID(lt, m);
|
||||
CHECK(!dd.isHeld(<->dd, m->id));
|
||||
// Printf("T%d MutexLock: %zx\n", thr->tid, s->deadlock_detector_id);
|
||||
bool has_deadlock = trylock
|
||||
? dd.onTryLock(<->dd, m->id)
|
||||
: dd.onLock(<->dd, m->id);
|
||||
DDReport *rep = 0;
|
||||
if (has_deadlock) {
|
||||
uptr path[10];
|
||||
uptr len = dd.findPathToHeldLock(<->dd, m->id,
|
||||
path, ARRAY_SIZE(path));
|
||||
CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that.
|
||||
rep = <->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(<->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
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -100,6 +100,3 @@ void MutexDestroy(Thread *thr, uptr m) {
|
|||
}
|
||||
|
||||
} // namespace __dsan
|
||||
|
||||
__attribute__((section(".preinit_array"), used))
|
||||
void (*__local_dsan_preinit)(void) = __dsan::Initialize;
|
||||
|
|
|
@ -36,6 +36,7 @@ struct Context {
|
|||
MutexHashMap mutex_map;
|
||||
};
|
||||
|
||||
void Initialize();
|
||||
void InitializeInterceptors();
|
||||
|
||||
void ThreadInit(Thread *thr);
|
||||
|
|
Loading…
Reference in New Issue