1XFAIL: target={{.*haiku.*}} 2RUN: rm -rf %t && split-file %s %t && cd %t 3RUN: %clang_pgogen -fprofile-update=atomic -fPIC foo.c -c -Xclang -fprofile-instrument-path="default_foo_%m.profraw" 4RUN: %clang_pgogen -fprofile-update=atomic -fPIC foo2.c -c -Xclang -fprofile-instrument-path="default_foo2_%m.profraw" 5RUN: %clang_pgogen -fprofile-update=atomic -shared foo.o -o shr_foo.o %if target={{.*aix.*}} %{ -bcdtors:mbr %} 6RUN: %clang_pgogen -fprofile-update=atomic -shared foo2.o -o shr_foo2.o 7 8RUN: %clang_pgogen common.c -c 9 10RUN: %clang_pgogen test1.c common.o -Xclang -fprofile-instrument-path="default_test1_%m.profraw" 11RUN: ./a.out 2>&1 | FileCheck %s -check-prefix=CHECK-FOO 12RUN: llvm-profdata show default_test1_*.profraw --counts --all-functions 2>&1 | \ 13RUN: FileCheck %s -check-prefix=CHECK-TEST1 14RUN: rm -f default* 15 16RUN: %clang_pgogen test2.c common.o -Xclang -fprofile-instrument-path="default_test2_%m.profraw" 17RUN: ./a.out 2>&1 | FileCheck %s -check-prefix=CHECK-FOO 18RUN: llvm-profdata show default_test2_*.profraw --counts --all-functions 2>&1 | \ 19RUN: FileCheck %s -check-prefix=CHECK-TEST2 20RUN: rm -f default* 21 22RUN: %clangxx_pgogen -lpthread test3.cpp common.o -Xclang -fprofile-instrument-path="default_test3_%m.profraw" 23RUN: ./a.out 2>&1 | FileCheck %s -check-prefix=CHECK-FOO-FOUR-THREADS 24 25CHECK-FOO: foo: 26CHECK-FOO: Block counts: [1] 27CHECK-FOO: foo2: 28CHECK-FOO: Block counts: [1] 29CHECK-FOO: foo: 30CHECK-FOO: Block counts: [2] 31 32CHECK-FOO-FOUR-THREADS: foo: 33CHECK-FOO-FOUR-THREADS: Block counts: [8] 34CHECK-FOO-FOUR-THREADS: foo2: 35CHECK-FOO-FOUR-THREADS: Block counts: [4] 36 37CHECK-TEST1: main: 38CHECK-TEST1: Block counts: [1, 0, 1, 0, 1, 1, 0] 39 40CHECK-TEST2: func1: 41CHECK-TEST2: Block counts: [4] 42CHECK-TEST2: func2: 43CHECK-TEST2: Block counts: [1] 44 45 46//--- foo.c 47void foo() {} 48 49//--- foo2.c 50void foo2() {} 51 52//--- common.c 53#include <dlfcn.h> 54#include <stdio.h> 55#include <stdlib.h> 56typedef void (*FN_PTR)(); 57int perform_check = 1; 58 59/* This function dlopen/dlclose shr_foo.a twice and shr_foo2.a once. Each time it 60 * dlopens a library, it runs the singleton function from that library. So the 61 * final counter value for foo and foo2 in each profile file is 2 and 1, resp. 62 */ 63int open_close_libs() { 64 void *handle, *handle2; 65 FN_PTR foo, foo2; 66 67#define OPEN_AND_RUN(HANDLE, SUF) \ 68 HANDLE = dlopen("./shr_" #SUF ".o", RTLD_NOW); \ 69 SUF = (void (*)())dlsym(HANDLE, #SUF); \ 70 if (SUF == NULL) { \ 71 fprintf(stderr, "unable to lookup symbol '%s': %s\n", #SUF, dlerror()); \ 72 return EXIT_FAILURE; \ 73 } \ 74 SUF(); 75 76#define CHECK_ONLY(SUF) \ 77 system("llvm-profdata show default_" #SUF "_*.profraw --counts --all-functions"); 78 79#define CLOSE_AND_CHECK(HANDLE, SUF) \ 80 dlclose(HANDLE); \ 81 if (perform_check) { CHECK_ONLY(SUF) } 82 83 OPEN_AND_RUN(handle, foo) 84 CLOSE_AND_CHECK(handle, foo) 85 86 OPEN_AND_RUN(handle2, foo2) 87 OPEN_AND_RUN(handle, foo) 88 CLOSE_AND_CHECK(handle2, foo2) 89 CLOSE_AND_CHECK(handle, foo) 90 return EXIT_SUCCESS; 91} 92void check_prof_files() { 93 CHECK_ONLY(foo) 94 CHECK_ONLY(foo2) 95} 96 97//--- test1.c 98int open_close_libs(); 99int main() { 100 open_close_libs(); 101} 102 103//--- test2.c 104#include <dlfcn.h> 105#include <stdio.h> 106#include <stdlib.h> 107#include <sys/wait.h> 108#include <unistd.h> 109 110__attribute__((noinline)) void func1() {} 111__attribute__((noinline)) void func2() {} 112void open_close_libs(); 113 114int main(void) { 115 int status; 116 func1(); 117 pid_t pid = fork(); 118 if (pid == -1) 119 return 1; 120 if (pid == 0) { // child 121 open_close_libs(); 122 func2(); 123 } 124 func1(); 125 if (pid) 126 wait(&status); 127 return 0; 128} 129 130//--- test3.cpp 131#include <sys/types.h> 132#include <thread> 133#include <unistd.h> 134 135extern "C" void check_prof_files(); 136extern "C" void open_close_libs(); 137extern int perform_check; 138 139template <typename T> 140void launcher(T func) { 141 auto t1 = std::thread(func); 142 auto t2 = std::thread(func); 143 auto t3 = std::thread(func); 144 auto t4 = std::thread(func); 145 146 t1.join(); 147 t2.join(); 148 t3.join(); 149 t4.join(); 150} 151 152int main() { 153 // don't check profiles generate inside open_close_libs because 154 // you'll get non-deterministic output due to threading. 155 perform_check = 0; 156 launcher<>(open_close_libs); 157 158 // instead, check the profiles manually here in the main thread. 159 check_prof_files(); 160 return 0; 161} 162