[compiler-rt] r189767 - tsan: properly intercept pthread_cond functions
Alexander Potapenko
glider at google.com
Tue Sep 3 05:19:58 PDT 2013
On Tue, Sep 3, 2013 at 4:11 PM, Dmitry Vyukov <dvyukov at google.com> wrote:
> On Tue, Sep 3, 2013 at 3:37 PM, Alexander Potapenko <glider at google.com> wrote:
>> Am I right this won't work properly if new versions of
>> pthread_cond_xxx are introduced or if the user has an old glibc?
>
> yes
>
>> Can this be checked or at least documented?
>
> how can we check it?
We can probably check whether the 2.3.2 versions are available. If
they aren't, the glibc is too old.
> where will such documentation be useful?
Next time the interface changes we'll spend less time debugging
spurious pthread_cond_wait behavior if there's a comment about that.
>
>> On Mon, Sep 2, 2013 at 10:06 PM, Dmitry Vyukov <dvyukov at google.com> wrote:
>>> Author: dvyukov
>>> Date: Mon Sep 2 13:06:28 2013
>>> New Revision: 189767
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=189767&view=rev
>>> Log:
>>> tsan: properly intercept pthread_cond functions
>>>
>>> Added:
>>> compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c
>>> Modified:
>>> compiler-rt/trunk/lib/interception/interception_linux.cc
>>> compiler-rt/trunk/lib/interception/interception_linux.h
>>> compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh
>>> compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
>>> compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
>>> compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
>>>
>>> Modified: compiler-rt/trunk/lib/interception/interception_linux.cc
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.cc?rev=189767&r1=189766&r2=189767&view=diff
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/interception/interception_linux.cc (original)
>>> +++ compiler-rt/trunk/lib/interception/interception_linux.cc Mon Sep 2 13:06:28 2013
>>> @@ -15,7 +15,6 @@
>>> #ifdef __linux__
>>> #include "interception.h"
>>>
>>> -#include <stddef.h> // for NULL
>>> #include <dlfcn.h> // for dlsym
>>>
>>> namespace __interception {
>>> @@ -24,6 +23,11 @@ bool GetRealFunctionAddress(const char *
>>> *func_addr = (uptr)dlsym(RTLD_NEXT, func_name);
>>> return real == wrapper;
>>> }
>>> +
>>> +void *GetFuncAddrVer(const char *func_name, const char *ver) {
>>> + return dlvsym(RTLD_NEXT, func_name, ver);
>>> +}
>>> +
>>> } // namespace __interception
>>>
>>>
>>>
>>> Modified: compiler-rt/trunk/lib/interception/interception_linux.h
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.h?rev=189767&r1=189766&r2=189767&view=diff
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/interception/interception_linux.h (original)
>>> +++ compiler-rt/trunk/lib/interception/interception_linux.h Mon Sep 2 13:06:28 2013
>>> @@ -25,6 +25,7 @@ namespace __interception {
>>> // returns true if a function with the given name was found.
>>> bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
>>> uptr real, uptr wrapper);
>>> +void *GetFuncAddrVer(const char *func_name, const char *ver);
>>> } // namespace __interception
>>>
>>> #define INTERCEPT_FUNCTION_LINUX(func) \
>>> @@ -33,5 +34,10 @@ bool GetRealFunctionAddress(const char *
>>> (::__interception::uptr)&(func), \
>>> (::__interception::uptr)&WRAP(func))
>>>
>>> +#define INTERCEPT_FUNCTION_VER(func, funcver, symver) \
>>> + __asm__(".symver "#funcver","#func"@"#symver); \
>>> + ::__interception::real_##funcver = (funcver##_f)(unsigned long) \
>>> + ::__interception::GetFuncAddrVer(#func, #symver)
>>> +
>>> #endif // INTERCEPTION_LINUX_H
>>> #endif // __linux__
>>>
>>> Added: compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c?rev=189767&view=auto
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c (added)
>>> +++ compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c Mon Sep 2 13:06:28 2013
>>> @@ -0,0 +1,44 @@
>>> +// RUN: %clang_tsan -O1 %s -o %t -lrt && %t 2>&1 | FileCheck %s
>>> +// Test that pthread_cond is properly intercepted,
>>> +// previously there were issues with versioned symbols.
>>> +// CHECK: OK
>>> +
>>> +#include <stdio.h>
>>> +#include <stdlib.h>
>>> +#include <pthread.h>
>>> +#include <time.h>
>>> +#include <errno.h>
>>> +
>>> +int main() {
>>> + typedef unsigned long long u64;
>>> + pthread_mutex_t m;
>>> + pthread_cond_t c;
>>> + pthread_condattr_t at;
>>> + struct timespec ts0, ts1, ts2;
>>> + int res;
>>> + u64 sleep;
>>> +
>>> + pthread_mutex_init(&m, 0);
>>> + pthread_condattr_init(&at);
>>> + pthread_condattr_setclock(&at, CLOCK_MONOTONIC);
>>> + pthread_cond_init(&c, &at);
>>> +
>>> + clock_gettime(CLOCK_MONOTONIC, &ts0);
>>> + ts1 = ts0;
>>> + ts1.tv_sec += 2;
>>> +
>>> + pthread_mutex_lock(&m);
>>> + do {
>>> + res = pthread_cond_timedwait(&c, &m, &ts1);
>>> + } while (res == 0);
>>> + pthread_mutex_unlock(&m);
>>> +
>>> + clock_gettime(CLOCK_MONOTONIC, &ts2);
>>> + sleep = (u64)ts2.tv_sec * 1000000000 + ts2.tv_nsec -
>>> + ((u64)ts0.tv_sec * 1000000000 + ts0.tv_nsec);
>>> + if (res != ETIMEDOUT)
>>> + exit(printf("bad return value %d, want %d\n", res, ETIMEDOUT));
>>> + if (sleep < 1000000000)
>>> + exit(printf("bad sleep duration %lluns, want %dns\n", sleep, 1000000000));
>>> + fprintf(stderr, "OK\n");
>>> +}
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh?rev=189767&r1=189766&r2=189767&view=diff
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh (original)
>>> +++ compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh Mon Sep 2 13:06:28 2013
>>> @@ -13,7 +13,7 @@ BLACKLIST=$ROOTDIR/lit_tests/Helpers/bla
>>>
>>> # TODO: add testing for all of -O0...-O3
>>> CFLAGS="-fsanitize=thread -fsanitize-blacklist=$BLACKLIST -fPIE -O1 -g -Wall"
>>> -LDFLAGS="-pie -lpthread -ldl $ROOTDIR/rtl/libtsan.a"
>>> +LDFLAGS="-pie -lpthread -ldl -lrt $ROOTDIR/rtl/libtsan.a"
>>>
>>> test_file() {
>>> SRC=$1
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=189767&r1=189766&r2=189767&view=diff
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Mon Sep 2 13:06:28 2013
>>> @@ -1051,46 +1051,43 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unl
>>> return res;
>>> }
>>>
>>> -// libpthread.so contains several versions of pthread_cond_init symbol.
>>> -// When we just dlsym() it, we get the wrong (old) version.
>>> -/*
>>> -TSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
>>> - SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
>>> - int res = REAL(pthread_cond_init)(c, a);
>>> +TSAN_INTERCEPTOR(int, pthread_cond_init_2_3_2, void *c, void *a) {
>>> + SCOPED_TSAN_INTERCEPTOR(pthread_cond_init_2_3_2, c, a);
>>> + int res = REAL(pthread_cond_init_2_3_2)(c, a);
>>> return res;
>>> }
>>> -*/
>>>
>>> -TSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
>>> - SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
>>> - int res = REAL(pthread_cond_destroy)(c);
>>> +TSAN_INTERCEPTOR(int, pthread_cond_destroy_2_3_2, void *c) {
>>> + SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy_2_3_2, c);
>>> + int res = REAL(pthread_cond_destroy_2_3_2)(c);
>>> return res;
>>> }
>>>
>>> -TSAN_INTERCEPTOR(int, pthread_cond_signal, void *c) {
>>> - SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, c);
>>> - int res = REAL(pthread_cond_signal)(c);
>>> +TSAN_INTERCEPTOR(int, pthread_cond_signal_2_3_2, void *c) {
>>> + SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal_2_3_2, c);
>>> + int res = REAL(pthread_cond_signal_2_3_2)(c);
>>> return res;
>>> }
>>>
>>> -TSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
>>> - SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, c);
>>> - int res = REAL(pthread_cond_broadcast)(c);
>>> +TSAN_INTERCEPTOR(int, pthread_cond_broadcast_2_3_2, void *c) {
>>> + SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast_2_3_2, c);
>>> + int res = REAL(pthread_cond_broadcast_2_3_2)(c);
>>> return res;
>>> }
>>>
>>> -TSAN_INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
>>> - SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, c, m);
>>> +TSAN_INTERCEPTOR(int, pthread_cond_wait_2_3_2, void *c, void *m) {
>>> + SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait_2_3_2, c, m);
>>> MutexUnlock(thr, pc, (uptr)m);
>>> - int res = REAL(pthread_cond_wait)(c, m);
>>> + int res = REAL(pthread_cond_wait_2_3_2)(c, m);
>>> MutexLock(thr, pc, (uptr)m);
>>> return res;
>>> }
>>>
>>> -TSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
>>> - SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
>>> +TSAN_INTERCEPTOR(int, pthread_cond_timedwait_2_3_2, void *c, void *m,
>>> + void *abstime) {
>>> + SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_2_3_2, c, m, abstime);
>>> MutexUnlock(thr, pc, (uptr)m);
>>> - int res = REAL(pthread_cond_timedwait)(c, m, abstime);
>>> + int res = REAL(pthread_cond_timedwait_2_3_2)(c, m, abstime);
>>> MutexLock(thr, pc, (uptr)m);
>>> return res;
>>> }
>>> @@ -1984,12 +1981,18 @@ void InitializeInterceptors() {
>>> TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
>>> TSAN_INTERCEPT(pthread_rwlock_unlock);
>>>
>>> - // TSAN_INTERCEPT(pthread_cond_init);
>>> - TSAN_INTERCEPT(pthread_cond_destroy);
>>> - TSAN_INTERCEPT(pthread_cond_signal);
>>> - TSAN_INTERCEPT(pthread_cond_broadcast);
>>> - TSAN_INTERCEPT(pthread_cond_wait);
>>> - TSAN_INTERCEPT(pthread_cond_timedwait);
>>> + INTERCEPT_FUNCTION_VER(pthread_cond_init, pthread_cond_init_2_3_2,
>>> + GLIBC_2.3.2);
>>> + INTERCEPT_FUNCTION_VER(pthread_cond_destroy, pthread_cond_destroy_2_3_2,
>>> + GLIBC_2.3.2);
>>> + INTERCEPT_FUNCTION_VER(pthread_cond_signal, pthread_cond_signal_2_3_2,
>>> + GLIBC_2.3.2);
>>> + INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, pthread_cond_broadcast_2_3_2,
>>> + GLIBC_2.3.2);
>>> + INTERCEPT_FUNCTION_VER(pthread_cond_wait, pthread_cond_wait_2_3_2,
>>> + GLIBC_2.3.2);
>>> + INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, pthread_cond_timedwait_2_3_2,
>>> + GLIBC_2.3.2);
>>>
>>> TSAN_INTERCEPT(pthread_barrier_init);
>>> TSAN_INTERCEPT(pthread_barrier_destroy);
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=189767&r1=189766&r2=189767&view=diff
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Mon Sep 2 13:06:28 2013
>>> @@ -169,12 +169,15 @@ void StatOutput(u64 *stat) {
>>> name[StatInt_pthread_rwlock_timedwrlock]
>>> = " pthread_rwlock_timedwrlock ";
>>> name[StatInt_pthread_rwlock_unlock] = " pthread_rwlock_unlock ";
>>> - name[StatInt_pthread_cond_init] = " pthread_cond_init ";
>>> - name[StatInt_pthread_cond_destroy] = " pthread_cond_destroy ";
>>> - name[StatInt_pthread_cond_signal] = " pthread_cond_signal ";
>>> - name[StatInt_pthread_cond_broadcast] = " pthread_cond_broadcast ";
>>> - name[StatInt_pthread_cond_wait] = " pthread_cond_wait ";
>>> - name[StatInt_pthread_cond_timedwait] = " pthread_cond_timedwait ";
>>> + name[StatInt_pthread_cond_init_2_3_2] = " pthread_cond_init ";
>>> + name[StatInt_pthread_cond_destroy_2_3_2]
>>> + = " pthread_cond_destroy ";
>>> + name[StatInt_pthread_cond_signal_2_3_2]= " pthread_cond_signal ";
>>> + name[StatInt_pthread_cond_broadcast_2_3_2]
>>> + = " pthread_cond_broadcast ";
>>> + name[StatInt_pthread_cond_wait_2_3_2] = " pthread_cond_wait ";
>>> + name[StatInt_pthread_cond_timedwait_2_3_2]
>>> + = " pthread_cond_timedwait ";
>>> name[StatInt_pthread_barrier_init] = " pthread_barrier_init ";
>>> name[StatInt_pthread_barrier_destroy] = " pthread_barrier_destroy ";
>>> name[StatInt_pthread_barrier_wait] = " pthread_barrier_wait ";
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=189767&r1=189766&r2=189767&view=diff
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Mon Sep 2 13:06:28 2013
>>> @@ -164,12 +164,12 @@ enum StatType {
>>> StatInt_pthread_rwlock_trywrlock,
>>> StatInt_pthread_rwlock_timedwrlock,
>>> StatInt_pthread_rwlock_unlock,
>>> - StatInt_pthread_cond_init,
>>> - StatInt_pthread_cond_destroy,
>>> - StatInt_pthread_cond_signal,
>>> - StatInt_pthread_cond_broadcast,
>>> - StatInt_pthread_cond_wait,
>>> - StatInt_pthread_cond_timedwait,
>>> + StatInt_pthread_cond_init_2_3_2,
>>> + StatInt_pthread_cond_destroy_2_3_2,
>>> + StatInt_pthread_cond_signal_2_3_2,
>>> + StatInt_pthread_cond_broadcast_2_3_2,
>>> + StatInt_pthread_cond_wait_2_3_2,
>>> + StatInt_pthread_cond_timedwait_2_3_2,
>>> StatInt_pthread_barrier_init,
>>> StatInt_pthread_barrier_destroy,
>>> StatInt_pthread_barrier_wait,
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>>
>>
>> --
>> Alexander Potapenko
>> Software Engineer
>> Google Moscow
--
Alexander Potapenko
Software Engineer
Google Moscow
More information about the llvm-commits
mailing list