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 <The NetBSD Foundation> Reviewers: joerg, dvyukov, vitalybuka Reviewed By: dvyukov Subscribers: llvm-commits, kubamracek, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D40262 llvm-svn: 318742
This commit is contained in:
parent
7ca5e58736
commit
d7c85137aa
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<atomic_uint32_t*>(o);
|
||||
else // On OS X, pthread_once_t has a header with a long-sized signature.
|
||||
|
||||
if (SANITIZER_MAC)
|
||||
a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
|
||||
else if (SANITIZER_NETBSD)
|
||||
a = static_cast<atomic_uint32_t*>
|
||||
((void *)((char *)o + __sanitizer::pthread_mutex_t_sz));
|
||||
else
|
||||
a = static_cast<atomic_uint32_t*>(o);
|
||||
|
||||
u32 v = atomic_load(a, memory_order_acquire);
|
||||
if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
|
||||
memory_order_relaxed)) {
|
||||
|
|
Loading…
Reference in New Issue