forked from OSchip/llvm-project
tsan/asan: support pthread_setname_np to set thread names
llvm-svn: 193602
This commit is contained in:
parent
da797048d9
commit
3e8432ee6c
|
|
@ -130,6 +130,8 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
|||
do { \
|
||||
} while (false)
|
||||
#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
|
||||
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
|
||||
asanThreadRegistry().SetThreadNameByUserId(thread, name)
|
||||
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
|
||||
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
|
|
|
|||
|
|
@ -1224,6 +1224,9 @@ extern "C" int *__errno_location(void);
|
|||
#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
|
||||
do { \
|
||||
} while (false) // FIXME
|
||||
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
|
||||
do { \
|
||||
} while (false) // FIXME
|
||||
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
|
||||
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
// COMMON_INTERCEPTOR_ON_EXIT
|
||||
// COMMON_INTERCEPTOR_MUTEX_LOCK
|
||||
// COMMON_INTERCEPTOR_MUTEX_UNLOCK
|
||||
// COMMON_INTERCEPTOR_SET_PTHREAD_NAME
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "interception/interception.h"
|
||||
#include "sanitizer_platform_interceptors.h"
|
||||
|
|
@ -34,19 +35,19 @@
|
|||
#endif // _WIN32
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
|
||||
#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, p, size)
|
||||
#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, p, size) {}
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_FD_ACCESS
|
||||
#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd)
|
||||
#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_MUTEX_LOCK
|
||||
#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m)
|
||||
#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) {}
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
|
||||
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m)
|
||||
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_STRCMP
|
||||
|
|
@ -2655,6 +2656,18 @@ INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
|
|||
#define INIT_TEMPNAM
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP
|
||||
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
|
||||
COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
|
||||
return REAL(pthread_setname_np)(thread, name);
|
||||
}
|
||||
#define INIT_PTHREAD_SETNAME_NP INTERCEPT_FUNCTION(pthread_setname_np);
|
||||
#else
|
||||
#define INIT_PTHREAD_SETNAME_NP
|
||||
#endif
|
||||
|
||||
|
||||
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
|
||||
INIT_STRCMP; \
|
||||
|
|
@ -2757,4 +2770,5 @@ INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
|
|||
INIT_TMPNAM; \
|
||||
INIT_TMPNAM_R; \
|
||||
INIT_TEMPNAM; \
|
||||
INIT_PTHREAD_SETNAME_NP; \
|
||||
/**/
|
||||
|
|
|
|||
|
|
@ -149,5 +149,6 @@
|
|||
|
||||
# define SANITIZER_INTERCEPT_PHTREAD_MUTEX SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_PTHREAD_COND SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP SI_LINUX_NOT_ANDROID
|
||||
|
||||
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
|
||||
|
|
|
|||
|
|
@ -200,6 +200,18 @@ void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
|
|||
tctx->SetName(name);
|
||||
}
|
||||
|
||||
void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) {
|
||||
BlockingMutexLock l(&mtx_);
|
||||
for (u32 tid = 0; tid < n_contexts_; tid++) {
|
||||
ThreadContextBase *tctx = threads_[tid];
|
||||
if (tctx != 0 && tctx->user_id == user_id &&
|
||||
tctx->status != ThreadStatusInvalid) {
|
||||
tctx->SetName(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadRegistry::DetachThread(u32 tid) {
|
||||
BlockingMutexLock l(&mtx_);
|
||||
CHECK_LT(tid, n_contexts_);
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ class ThreadRegistry {
|
|||
ThreadContextBase *FindThreadContextByOsIDLocked(uptr os_id);
|
||||
|
||||
void SetThreadName(u32 tid, const char *name);
|
||||
void SetThreadNameByUserId(uptr user_id, const char *name);
|
||||
void DetachThread(u32 tid);
|
||||
void JoinThread(u32 tid, void *arg);
|
||||
void FinishThread(u32 tid);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: %clangxx_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int Global;
|
||||
|
||||
void *Thread1(void *x) {
|
||||
sleep(1);
|
||||
Global++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *Thread2(void *x) {
|
||||
pthread_setname_np(pthread_self(), "foobar2");
|
||||
Global--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t t[2];
|
||||
pthread_create(&t[0], 0, Thread1, 0);
|
||||
pthread_create(&t[1], 0, Thread2, 0);
|
||||
pthread_setname_np(t[0], "foobar1");
|
||||
pthread_join(t[0], NULL);
|
||||
pthread_join(t[1], NULL);
|
||||
}
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: data race
|
||||
// CHECK: Thread T1 'foobar1'
|
||||
// CHECK: Thread T2 'foobar2'
|
||||
|
||||
|
|
@ -1837,38 +1837,54 @@ struct TsanInterceptorContext {
|
|||
#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
|
||||
do { \
|
||||
} while (false)
|
||||
|
||||
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
|
||||
MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
|
||||
((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
|
||||
true)
|
||||
|
||||
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
|
||||
MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
|
||||
((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
|
||||
false)
|
||||
|
||||
#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
|
||||
SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
|
||||
TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
|
||||
ctx = (void *)&_ctx; \
|
||||
(void) ctx;
|
||||
|
||||
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
|
||||
FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
|
||||
|
||||
#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
|
||||
FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
|
||||
|
||||
#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \
|
||||
FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd)
|
||||
|
||||
#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
|
||||
FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
|
||||
|
||||
#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
|
||||
ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
|
||||
|
||||
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
|
||||
CTX()->thread_registry->SetThreadNameByUserId(thread, name)
|
||||
|
||||
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
|
||||
|
||||
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \
|
||||
OnExit(((TsanInterceptorContext *) ctx)->thr)
|
||||
|
||||
#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) \
|
||||
MutexLock(((TsanInterceptorContext *)ctx)->thr, \
|
||||
((TsanInterceptorContext *)ctx)->pc, (uptr)m)
|
||||
|
||||
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \
|
||||
MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \
|
||||
((TsanInterceptorContext *)ctx)->pc, (uptr)m)
|
||||
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
|
||||
#define TSAN_SYSCALL() \
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ void StatOutput(u64 *stat) {
|
|||
name[StatInt_pthread_barrier_wait] = " pthread_barrier_wait ";
|
||||
name[StatInt_pthread_once] = " pthread_once ";
|
||||
name[StatInt_pthread_getschedparam] = " pthread_getschedparam ";
|
||||
name[StatInt_pthread_setname_np] = " pthread_setname_np ";
|
||||
name[StatInt_sem_init] = " sem_init ";
|
||||
name[StatInt_sem_destroy] = " sem_destroy ";
|
||||
name[StatInt_sem_wait] = " sem_wait ";
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ enum StatType {
|
|||
StatInt_pthread_barrier_wait,
|
||||
StatInt_pthread_once,
|
||||
StatInt_pthread_getschedparam,
|
||||
StatInt_pthread_setname_np,
|
||||
StatInt_sem_init,
|
||||
StatInt_sem_destroy,
|
||||
StatInt_sem_wait,
|
||||
|
|
|
|||
Loading…
Reference in New Issue