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 12 int GLOB_SHARED = 0; 13 14 extern "C" 15 void init_so() { 16 barrier_init(&barrier, 2); 17 } 18 19 extern "C" 20 void *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 35 int GLOB = 0; 36 37 void *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 46 void 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 54 int 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