diff --git a/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c b/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c --- a/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c @@ -1,4 +1,4 @@ -// REQUIRES: darwin +// REQUIRES: darwin || linux // Test the online merging mode (%m) along with continuous mode (%c). // @@ -8,9 +8,13 @@ // Create two DSOs and a driver program that uses them. // RUN: echo "void dso1(void) {}" > dso1.c // RUN: echo "void dso2(void) {}" > dso2.c -// RUN: %clang_pgogen -dynamiclib -o %t.dir/dso1.dylib dso1.c -mllvm -instrprof-atomic-counter-update-all=1 -// RUN: %clang_pgogen -dynamiclib -o %t.dir/dso2.dylib dso2.c -mllvm -instrprof-atomic-counter-update-all=1 -// RUN: %clang_pgogen -o main.exe %s %t.dir/dso1.dylib %t.dir/dso2.dylib -mllvm -instrprof-atomic-counter-update-all=1 +// RUN: %clang_pgogen -o %t.dir/dso1.dylib dso1.c -mllvm -instrprof-atomic-counter-update-all=1 \ +// RUN: %if linux %{ -shared -fpic -mllvm -runtime-counter-relocation=true %} %else %{ -dynamiclib %} +// RUN: %clang_pgogen -o %t.dir/dso2.dylib dso2.c -mllvm -instrprof-atomic-counter-update-all=1 \ +// RUN: %if linux %{ -shared -fpic -mllvm -runtime-counter-relocation=true %} %else %{ -dynamiclib %} +// RUN: %clang_pgogen -o main.exe %s %t.dir/dso1.dylib %t.dir/dso2.dylib -mllvm -instrprof-atomic-counter-update-all=1 \ +// RUN: %if linux %{ -mllvm -runtime-counter-relocation=true %} + // // === Round 1 === // Test merging+continuous mode without any file contention. diff --git a/compiler-rt/test/profile/ContinuousSyncMode/set-file-object.c b/compiler-rt/test/profile/ContinuousSyncMode/set-file-object.c --- a/compiler-rt/test/profile/ContinuousSyncMode/set-file-object.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/set-file-object.c @@ -1,17 +1,18 @@ -// REQUIRES: darwin || linux +// REQUIRES: darwin || linux || windows // Test using __llvm_profile_set_file_object in continuous mode (%c). // Create & cd into a temporary directory. // RUN: rm -rf %t.dir && mkdir -p %t.dir && cd %t.dir // The -mllvm -runtime-counter-relocation=true flag has effect only on linux. -// RUN: %clang -fprofile-instr-generate -fcoverage-mapping -mllvm -instrprof-atomic-counter-update-all=1 -mllvm -runtime-counter-relocation=true -o main.exe %s +// RUN: %clang -fprofile-instr-generate -fcoverage-mapping -mllvm -instrprof-atomic-counter-update-all=1 \ +// RUN: %if !darwin %{ -mllvm -runtime-counter-relocation=true %} -o main.exe %s -// Test continuous mode with __llvm_profile_set_file_object with mergin disabled. +// Test continuous mode with __llvm_profile_set_file_object with merging disabled. // RUN: env LLVM_PROFILE_FILE="%t.dir/profdir/%c%mprofraw.old" %run %t.dir/main.exe nomerge %t.dir/profdir/profraw.new 2>&1 | FileCheck %s -check-prefix=WARN // WARN: LLVM Profile Warning: __llvm_profile_set_file_object(fd={{[0-9]+}}) not supported in continuous sync mode when merging is disabled -// Test continuous mode with __llvm_profile_set_file_object with mergin enabled. +// Test continuous mode with __llvm_profile_set_file_object with merging enabled. // RUN: rm -rf %t.dir/profdir/ // RUN: env LLVM_PROFILE_FILE="%t.dir/profdir/%c%mprofraw.old" %run %t.dir/main.exe merge %t.dir/profdir/profraw.new 'LLVM_PROFILE_FILE=%t.dir/profdir/%c%m.profraw' // RUN: llvm-profdata merge -o %t.dir/profdir/profdata %t.dir/profdir/profraw.new @@ -34,13 +35,9 @@ // ZERO: Block counts: [] // ZERO: Instrumentation level: Front-end -#include #include #include -#include -#include - const int num_child_procs_to_spawn = 32; extern int __llvm_profile_is_continuous_mode_enabled(void); @@ -50,6 +47,94 @@ return 0; } +#if defined(_WIN32) +#include +#define CMD_LEN 4096 +int create_and_wait_process(char* binary_path, char* file_name, char* env) { + int I; + HANDLE child_pids[num_child_procs_to_spawn]; + char child_cmd[CMD_LEN]; + ZeroMemory(child_cmd, sizeof(child_cmd)); + strcat_s(child_cmd, CMD_LEN, binary_path); + strcat_s(child_cmd, CMD_LEN, " set "); + strcat_s(child_cmd, CMD_LEN, file_name); + for (I = 0; I < num_child_procs_to_spawn; ++I) { + // Start the child process. + STARTUPINFO si; + ZeroMemory(&si, sizeof(si)); + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + if (!CreateProcess(NULL, // No module name (use command line) + child_cmd, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + env, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi) // Pointer to PROCESS_INFORMATION structure + ) { + fprintf(stderr, "Child %d could not be spawned: %lu\n", I, + GetLastError()); + return 1; + } + child_pids[I] = pi.hProcess; + } + for (I = 0; I < num_child_procs_to_spawn; ++I) { + DWORD exit_code; + WaitForSingleObject(child_pids[I], INFINITE); + if (!GetExitCodeProcess(child_pids[I], &exit_code)) { + fprintf(stderr, "Failed to get exit code of child %d.\n", I); + return 1; + } + if (exit_code != 0) { + fprintf(stderr, "Child %d did not exit with code 0: %lu.\n", I, exit_code); + return 1; + } + } + return 0; +} +#else +#include +#include +#include +int create_and_wait_process(char* binary_path, char* file_name, char* env) { + int I; + pid_t child_pids[num_child_procs_to_spawn]; + char *const child_argv[] = {binary_path, "set", file_name, NULL}; + char *const envp[] = {env, NULL}; + for (I = 0; I < num_child_procs_to_spawn; ++I) { + int ret = + posix_spawn(&child_pids[I], binary_path, NULL, NULL, child_argv, envp); + if (ret != 0) { + fprintf(stderr, "Child %d could not be spawned: ret = %d, msg = %s\n", + I, ret, strerror(ret)); + return 1; + } + } + for (I = 0; I < num_child_procs_to_spawn; ++I) { + int status; + pid_t waited_pid = waitpid(child_pids[I], &status, 0); + if (waited_pid != child_pids[I]) { + fprintf(stderr, "Failed to wait on child %d\n", I); + return 1; + } + if (!WIFEXITED(status)) { + fprintf(stderr, "Child %d did not terminate normally\n", I); + return 1; + } + int return_status = WEXITSTATUS(status); + if (return_status != 0) { + fprintf(stderr, "Child %d exited with non zero status %d\n", I, + return_status); + return 1; + } + } + return 0; +} +#endif + int main(int argc, char **argv) { char *file_name = argv[2]; FILE *file = fopen(file_name, "a+b"); @@ -57,36 +142,8 @@ __llvm_profile_set_file_object(file, 0); else if (strcmp(argv[1], "merge") == 0) { // Parent process. - int I; - pid_t child_pids[num_child_procs_to_spawn]; - char *const child_argv[] = {argv[0], "set", file_name, NULL}; - char *const child_envp[] = {argv[3], NULL}; - for (I = 0; I < num_child_procs_to_spawn; ++I) { - int ret = - posix_spawn(&child_pids[I], argv[0], NULL, NULL, child_argv, child_envp); - if (ret != 0) { - fprintf(stderr, "Child %d could not be spawned: ret = %d, msg = %s\n", - I, ret, strerror(ret)); - return 1; - } - } - for (I = 0; I < num_child_procs_to_spawn; ++I) { - int status; - pid_t waited_pid = waitpid(child_pids[I], &status, 0); - if (waited_pid != child_pids[I]) { - fprintf(stderr, "Failed to wait on child %d\n", I); - return 1; - } - if (!WIFEXITED(status)) { - fprintf(stderr, "Child %d did not terminate normally\n", I); - return 1; - } - int return_status = WEXITSTATUS(status); - if (return_status != 0) { - fprintf(stderr, "Child %d exited with non zero status %d\n", I, - return_status); - return 1; - } + if (create_and_wait_process(argv[0], file_name, argv[3])) { + return 1; } } else if (strcmp(argv[1], "set") == 0) { // Child processes.