forked from apple/darwin-xnu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
perf_kdebug.c
168 lines (142 loc) · 4.85 KB
/
perf_kdebug.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#ifdef T_NAMESPACE
#undef T_NAMESPACE
#endif
#include <darwintest.h>
#include <sys/kdebug.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
T_GLOBAL_META(
T_META_NAMESPACE("xnu.perf.kdebug"),
T_META_ASROOT(true),
T_META_CHECK_LEAKS(false),
T_META_TAG_PERF
);
//
// Helper functions for direct control over the kernel trace facility.
//
static void _sysctl_reset() {
int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDREMOVE };
if(sysctl(mib, 3, NULL, NULL, NULL, 0)) {
T_FAIL("KERN_KDREMOVE sysctl failed");
}
}
static void _sysctl_setbuf(uint32_t capacity) {
int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSETBUF, (int)capacity };
if (sysctl(mib, 4, NULL, NULL, NULL, 0)) {
T_FAIL("KERN_KDSETBUF sysctl failed");
}
}
static void _sysctl_setup() {
int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSETUP };
if (sysctl(mib, 3, NULL, NULL, NULL, 0)) {
T_FAIL("KERN_KDSETUP sysctl failed");
}
}
static void _sysctl_enable(int value)
{
int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDENABLE, value };
if (sysctl(mib, 4, NULL, NULL, NULL, 0) < 0) {
T_FAIL("KERN_KDENABLE sysctl failed");
}
}
static void _sysctl_enable_typefilter(uint8_t* type_filter_bitmap) {
int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSET_TYPEFILTER };
size_t needed = KDBG_TYPEFILTER_BITMAP_SIZE;
if(sysctl(mib, 3, type_filter_bitmap, &needed, NULL, 0)) {
T_FAIL("KERN_KDSET_TYPEFILTER sysctl failed");
}
}
static void _sysctl_nowrap(bool is_nowrap) {
int mib[] = { CTL_KERN, KERN_KDEBUG, is_nowrap ? KERN_KDEFLAGS : KERN_KDDFLAGS, KDBG_NOWRAP };
if (sysctl(mib, 4, NULL, NULL, NULL, 0)) {
T_FAIL("KDBG_NOWRAP sysctl failed");
}
}
static void enable_tracing(bool value) {
_sysctl_enable(value ? KDEBUG_ENABLE_TRACE : 0);
}
static void enable_typefilter_all_reject() {
uint8_t type_filter_bitmap[KDBG_TYPEFILTER_BITMAP_SIZE];
memset(type_filter_bitmap, 0, sizeof(type_filter_bitmap));
_sysctl_enable_typefilter(type_filter_bitmap);
}
static void enable_typefilter_all_pass() {
uint8_t type_filter_bitmap[KDBG_TYPEFILTER_BITMAP_SIZE];
memset(type_filter_bitmap, 0xff, sizeof(type_filter_bitmap));
_sysctl_enable_typefilter(type_filter_bitmap);
}
static void loop_kdebug_trace(dt_stat_time_t s) {
do {
dt_stat_token start = dt_stat_time_begin(s);
for (uint32_t i = 0; i<100; i++) {
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
kdebug_trace(0x97000000 | DBG_FUNC_NONE, i, i, i, i);
}
dt_stat_time_end_batch(s, 1000, start);
} while (!dt_stat_stable(s));
}
static void loop_getppid(dt_stat_time_t s) {
do {
dt_stat_token start = dt_stat_time_begin(s);
for (uint32_t i = 0; i<100; i++) {
getppid();
getppid();
getppid();
getppid();
getppid();
getppid();
getppid();
getppid();
getppid();
getppid();
}
dt_stat_time_end_batch(s, 1000, start);
} while (!dt_stat_stable(s));
}
static void reset_kdebug_trace(void) {
_sysctl_reset();
}
static void test(const char* test_name, void (^pretest_setup)(void), void (*test)(dt_stat_time_t s)) {
T_ATEND(reset_kdebug_trace);
_sysctl_reset();
_sysctl_setbuf(1000000);
_sysctl_nowrap(false);
_sysctl_setup();
pretest_setup();
dt_stat_time_t s = dt_stat_time_create("%s", test_name);
test(s);
dt_stat_finalize(s);
}
//
// Begin tests...
//
T_DECL(kdebug_trace_baseline_syscall,
"Test the latency of a syscall while kernel tracing is disabled") {
test("kdebug_trace_baseline_syscall", ^{ enable_tracing(false); }, loop_getppid);
}
T_DECL(kdebug_trace_kdbg_disabled,
"Test the latency of kdebug_trace while kernel tracing is disabled") {
test("kdebug_trace_kdbg_disabled", ^{ enable_tracing(false); }, loop_kdebug_trace);
}
T_DECL(kdebug_trace_kdbg_enabled,
"Test the latency of kdebug_trace while kernel tracing is enabled with no typefilter") {
test("kdebug_trace_kdbg_enabled", ^{ enable_tracing(true); }, loop_kdebug_trace);
}
T_DECL(kdebug_trace_kdbg_enabled_typefilter_pass,
"Test the latency of kdebug_trace while kernel tracing is enabled with a typefilter that passes the event") {
test("kdebug_trace_kdbg_enabled_typefilter_pass", ^{ enable_tracing(true); enable_typefilter_all_pass(); }, loop_kdebug_trace);
}
T_DECL(kdebug_trace_kdbg_enabled_typefilter_reject,
"Test the latency of kdebug_trace while kernel tracing is enabled with a typefilter that rejects the event") {
test("kdebug_trace_kdbg_enabled_typefilter_reject", ^{ enable_tracing(true); enable_typefilter_all_reject(); }, loop_kdebug_trace);
}