]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/darwintests/perf_exit.c
d45a6481b59d77e9044198aee1e5d71c01684c13
[apple/xnu.git] / tools / tests / darwintests / perf_exit.c
1 #include <sys/kdebug.h>
2 #include <ktrace.h>
3 #include <spawn.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #include <darwintest.h>
8
9 // From bsd/sys/proc_internal.h
10 #define PID_MAX 99999
11
12 T_DECL(exit, "exit(2) time from syscall start to end", T_META_TYPE_PERF, T_META_CHECK_LEAKS(NO)) {
13 _Atomic static int ended = 0;
14 dispatch_queue_t spawn_queue;
15
16 dt_stat_time_t s = dt_stat_time_create("time");
17
18 uint64_t *begin_ts = malloc(sizeof(uint64_t) * PID_MAX);
19 if (begin_ts == NULL) {
20 T_FAIL("Error allocating timestamp array");
21 }
22
23 ktrace_session_t session;
24 session = ktrace_session_create();
25 if (session == NULL) {
26 T_FAIL("Error creating ktrace session");
27 }
28
29 ktrace_set_completion_handler(session, ^{
30 free(begin_ts);
31 dt_stat_finalize(s);
32 T_END;
33 });
34
35 ktrace_set_signal_handler(session);
36
37 // We are only interested by the process we launched
38 ktrace_filter_process(session, "true");
39
40 ktrace_events_single(session, (BSDDBG_CODE(DBG_BSD_EXCP_SC, 1) | DBG_FUNC_START), ^(ktrace_event_t e) {
41 pid_t pid = ktrace_get_pid_for_thread(session, e->threadid);
42 if (pid > PID_MAX) {
43 T_FAIL("Invalid pid returned by ktrace_get_pid_for_thread: %d\n", pid);
44 }
45 begin_ts[pid] = e->timestamp;
46
47 });
48 ktrace_events_single(session, (BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_EXIT) | DBG_FUNC_END), ^(ktrace_event_t e) {
49 pid_t pid = ktrace_get_pid_for_thread(session, e->threadid);
50 if (pid > PID_MAX) {
51 T_FAIL("Invalid pid returned by ktrace_get_pid_for_thread: %d\n", pid);
52 }
53 if (begin_ts[pid] == 0) {
54 return;
55 }
56 uint64_t delta = e->timestamp - begin_ts[pid];
57 if (!dt_stat_stable(s)) {
58 dt_stat_mach_time_add(s, delta);
59 }
60 else {
61 ended = 1;
62 ktrace_end(session, 1);
63 }
64 });
65
66 int ret = ktrace_start(session, dispatch_get_main_queue());
67 if (ret != 0) {
68 T_FAIL("Error starting ktrace");
69 }
70
71 // Spawn processes continuously until the test is over
72 spawn_queue = dispatch_queue_create("spawn_queue", NULL);
73 dispatch_async(spawn_queue, ^(void) {
74 while (!ended) {
75 pid_t pid;
76 int status;
77 char *args[] = {"/usr/bin/true", NULL};
78 int err = posix_spawn(&pid, args[0], NULL, NULL, args, NULL);
79 if (err)
80 T_FAIL("posix_spawn returned %d", err);
81
82 waitpid(pid, &status, 0);
83 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
84 T_FAIL("Child process of posix_spawn failed to run");
85 }
86 });
87
88 dispatch_main();
89 }