1// Check that if the list of shared libraries changes between the two race 2// reports, the second report occurring in a new shared library is still 3// symbolized correctly. 4 5// RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so 6// RUN: %clangxx_tsan -O1 %s -o %t -rdynamic && %deflake %run %t | FileCheck %s 7 8#ifdef BUILD_SO 9 10#include "test.h" 11 12int GLOB_SHARED = 0; 13 14extern "C" 15void init_so() { 16 barrier_init(&barrier, 2); 17} 18 19extern "C" 20void *write_from_so(void *unused) { 21 if (unused == 0) 22 barrier_wait(&barrier); 23 GLOB_SHARED++; 24 if (unused != 0) 25 barrier_wait(&barrier); 26 return NULL; 27} 28 29#else // BUILD_SO 30 31#include "test.h" 32#include <dlfcn.h> 33#include <string> 34 35int GLOB = 0; 36 37void *write_glob(void *unused) { 38 if (unused == 0) 39 barrier_wait(&barrier); 40 GLOB++; 41 if (unused != 0) 42 barrier_wait(&barrier); 43 return NULL; 44} 45 46void race_two_threads(void *(*access_callback)(void *unused)) { 47 pthread_t t1, t2; 48 pthread_create(&t1, NULL, access_callback, (void*)1); 49 pthread_create(&t2, NULL, access_callback, NULL); 50 pthread_join(t1, NULL); 51 pthread_join(t2, NULL); 52} 53 54int main(int argc, char *argv[]) { 55 barrier_init(&barrier, 2); 56 std::string path = std::string(argv[0]) + std::string("-so.so"); 57 race_two_threads(write_glob); 58 // CHECK: write_glob 59 void *lib = dlopen(path.c_str(), RTLD_NOW); 60 if (!lib) { 61 printf("error in dlopen(): %s\n", dlerror()); 62 return 1; 63 } 64 void (*init_so)(); 65 *(void **)&init_so = dlsym(lib, "init_so"); 66 init_so(); 67 void *(*write_from_so)(void *unused); 68 *(void **)&write_from_so = dlsym(lib, "write_from_so"); 69 race_two_threads(write_from_so); 70 // CHECK: write_from_so 71 return 0; 72} 73 74#endif // BUILD_SO 75