1 #ifdef T_NAMESPACE 2 #undef T_NAMESPACE 3 #endif 4 #include <darwintest.h> 5 6 #include <spawn.h> 7 #include <stdlib.h> 8 #include <unistd.h> 9 10 T_GLOBAL_META( 11 T_META_NAMESPACE("xnu.perf"), 12 T_META_CHECK_LEAKS(false), 13 T_META_TAG_PERF 14 ); 15 16 #define SPAWN_MEASURE_LOOP(s) \ 17 char *args[] = {"/usr/bin/true", NULL}; \ 18 int err; \ 19 pid_t pid; \ 20 int status; \ 21 while (!dt_stat_stable(s)) { \ 22 T_STAT_MEASURE(s) { \ 23 err = posix_spawn(&pid, args[0], NULL, NULL, args, NULL); \ 24 } \ 25 if (err) { \ 26 T_FAIL("posix_spawn returned %d", err); \ 27 } \ 28 waitpid(pid, &status, 0); \ 29 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { \ 30 T_FAIL("Child process of posix_spawn failed to run"); \ 31 } \ 32 } 33 34 T_DECL(posix_spawn_platform_binary_latency, "posix_spawn platform binary latency", T_META_TAG_VM_NOT_ELIGIBLE) { 35 { 36 dt_stat_time_t s = dt_stat_time_create("time"); 37 SPAWN_MEASURE_LOOP(s); 38 dt_stat_finalize(s); 39 } 40 41 { 42 dt_stat_thread_cpu_time_t s = dt_stat_thread_cpu_time_create("on_cpu_time"); 43 SPAWN_MEASURE_LOOP(s); 44 dt_stat_finalize(s); 45 } 46 } 47 48 #define FORK_MEASURE_LOOP(s) \ 49 pid_t pid; \ 50 int status; \ 51 while (!dt_stat_stable(s)) { \ 52 T_STAT_MEASURE(s) { \ 53 pid = fork(); \ 54 if (pid == 0) \ 55 exit(0); \ 56 else if (pid == -1) \ 57 T_FAIL("fork returned -1"); \ 58 } \ 59 waitpid(pid, &status, 0); \ 60 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { \ 61 T_FAIL("forked process failed to exit properly"); \ 62 } \ 63 } 64 65 T_DECL(fork, "fork latency", T_META_TAG_VM_NOT_ELIGIBLE) { 66 { 67 dt_stat_time_t s = dt_stat_time_create("time"); 68 FORK_MEASURE_LOOP(s); 69 dt_stat_finalize(s); 70 } 71 { 72 dt_stat_thread_cpu_time_t s = dt_stat_thread_cpu_time_create("on_cpu_time"); 73 FORK_MEASURE_LOOP(s); 74 dt_stat_finalize(s); 75 } 76 } 77