xref: /llvm-project/compiler-rt/test/profile/Windows/Inputs/instrprof-multiprocess.c (revision 900d8a9a3b4efeefddd310e92219741d98e7270b)
1 /* This is a test case where the parent process forks 10 children
2  * which contend to merge profile data to the same file. With
3  * file locking support, the data from each child should not
4  * be lost.
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <windows.h>
9 
spawn_child(PROCESS_INFORMATION * pi,int child_num)10 void spawn_child(PROCESS_INFORMATION *pi, int child_num) {
11   wchar_t child_str[10];
12   _itow(child_num, child_str, 10);
13   if (!SetEnvironmentVariableW(L"CHILD_NUM", child_str)) {
14     printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());
15     fflush(stdout);
16     exit(1);
17   }
18 
19   STARTUPINFOW si;
20   memset(&si, 0, sizeof(si));
21   si.cb = sizeof(si);
22 
23   memset(pi, 0, sizeof(PROCESS_INFORMATION));
24 
25   if (!CreateProcessW(NULL,              // No module name (use command line)
26                       GetCommandLineW(), // Command line
27                       NULL,              // Process handle not inheritable
28                       NULL,              // Thread handle not inheritable
29                       TRUE,              // Set handle inheritance to TRUE
30                       0,                 // No flags
31                       NULL,              // Use parent's environment block
32                       NULL,              // Use parent's starting directory
33                       &si, pi)) {
34     printf("CreateProcess failed (0x%08lx).\n", GetLastError());
35     fflush(stdout);
36     exit(1);
37   }
38 }
39 
wait_child(PROCESS_INFORMATION * pi)40 int wait_child(PROCESS_INFORMATION *pi) {
41   WaitForSingleObject(pi->hProcess, INFINITE);
42 
43   DWORD exit_code;
44   if (!GetExitCodeProcess(pi->hProcess, &exit_code)) {
45     printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());
46     fflush(stdout);
47     exit(1);
48   }
49 
50   CloseHandle(pi->hProcess);
51   CloseHandle(pi->hThread);
52 
53   return exit_code;
54 }
55 
56 #define NUM_CHILDREN 10
57 
foo(int num)58 int foo(int num) {
59   if (num < (NUM_CHILDREN / 2)) {
60     return 1;
61   } else if (num < NUM_CHILDREN) {
62     return 2;
63   }
64   return 3;
65 }
66 
main(int argc,char * argv[])67 int main(int argc, char *argv[]) {
68   char *child_str = getenv("CHILD_NUM");
69   if (!child_str) {
70     PROCESS_INFORMATION child[NUM_CHILDREN];
71     // In parent
72     for (int i = 0; i < NUM_CHILDREN; i++) {
73       spawn_child(&child[i], i);
74     }
75     for (int i = 0; i < NUM_CHILDREN; i++) {
76       wait_child(&child[i]);
77     }
78     return 0;
79   } else {
80     // In child
81     int child_num = atoi(child_str);
82     int result = foo(child_num);
83     if (result == 3) {
84       fprintf(stderr, "Invalid child count!");
85       return 1;
86     }
87     return 0;
88   }
89 }
90