From: Kamil Rytarowski Date: Tue, 21 Nov 2017 09:36:07 +0000 (+0000) Subject: Correct NetBSD support in pthread_once(3)/TSan X-Git-Tag: llvmorg-6.0.0-rc1~2927 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d7c85137aa392e8879dd7d37f3bb951def683e08;p=platform%2Fupstream%2Fllvm.git Correct NetBSD support in pthread_once(3)/TSan Summary: The pthread_once(3)/NetBSD type is built with the following structure: struct __pthread_once_st { pthread_mutex_t pto_mutex; int pto_done; }; Set the pto_done position as shifted by __sanitizer::pthread_mutex_t_sz from the beginning of the pthread_once struct. This corrects deadlocks when the pthread_once(3) function is used. Sponsored by Reviewers: joerg, dvyukov, vitalybuka Reviewed By: dvyukov Subscribers: llvm-commits, kubamracek, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D40262 llvm-svn: 318742 --- diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc index b973f0d..108e196 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -83,6 +83,7 @@ unsigned siginfo_t_sz = sizeof(siginfo_t); unsigned struct_sigaction_sz = sizeof(struct sigaction); unsigned struct_itimerval_sz = sizeof(struct itimerval); unsigned pthread_t_sz = sizeof(pthread_t); +unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t); unsigned pthread_cond_t_sz = sizeof(pthread_cond_t); unsigned pid_t_sz = sizeof(pid_t); unsigned timeval_sz = sizeof(timeval); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h index baba42c..a548470 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -38,6 +38,7 @@ extern unsigned struct_rusage_sz; extern unsigned siginfo_t_sz; extern unsigned struct_itimerval_sz; extern unsigned pthread_t_sz; +extern unsigned pthread_mutex_t_sz; extern unsigned pthread_cond_t_sz; extern unsigned pid_t_sz; extern unsigned timeval_sz; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index dd02b9b..f12e820 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -210,6 +210,7 @@ namespace __sanitizer { unsigned struct_sigaction_sz = sizeof(struct sigaction); unsigned struct_itimerval_sz = sizeof(struct itimerval); unsigned pthread_t_sz = sizeof(pthread_t); + unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t); unsigned pthread_cond_t_sz = sizeof(pthread_cond_t); unsigned pid_t_sz = sizeof(pid_t); unsigned timeval_sz = sizeof(timeval); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index c593586..4aa04f3 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -46,6 +46,7 @@ namespace __sanitizer { extern unsigned siginfo_t_sz; extern unsigned struct_itimerval_sz; extern unsigned pthread_t_sz; + extern unsigned pthread_mutex_t_sz; extern unsigned pthread_cond_t_sz; extern unsigned pid_t_sz; extern unsigned timeval_sz; diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index df8c5e3..611a3f7 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -1354,10 +1354,15 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { if (o == 0 || f == 0) return errno_EINVAL; atomic_uint32_t *a; - if (!SANITIZER_MAC) - a = static_cast(o); - else // On OS X, pthread_once_t has a header with a long-sized signature. + + if (SANITIZER_MAC) a = static_cast((void *)((char *)o + sizeof(long_t))); + else if (SANITIZER_NETBSD) + a = static_cast + ((void *)((char *)o + __sanitizer::pthread_mutex_t_sz)); + else + a = static_cast(o); + u32 v = atomic_load(a, memory_order_acquire); if (v == 0 && atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) {