1 #include <mach/port.h>
2 #include <mach/mach_init.h>
3 #include <mach/mach_port.h>
4 #include <sys/sysctl.h>
5 #include <dispatch/dispatch.h>
6 #include <darwintest.h>
7 #include <darwintest_utils.h>
8
9 T_GLOBAL_META(
10 T_META_NAMESPACE("xnu.ipc"),
11 T_META_RADAR_COMPONENT_NAME("xnu"),
12 T_META_RADAR_COMPONENT_VERSION("IPC"),
13 T_META_CHECK_LEAKS(false));
14
15 static int64_t
run_sysctl_test(const char * t,int64_t value)16 run_sysctl_test(const char *t, int64_t value)
17 {
18 char name[1024];
19 int64_t result = 0;
20 size_t s = sizeof(value);
21 int rc;
22
23 snprintf(name, sizeof(name), "debug.test.%s", t);
24 rc = sysctlbyname(name, &result, &s, &value, s);
25 T_ASSERT_POSIX_SUCCESS(rc, "sysctlbyname(%s)", t);
26 return result;
27 }
28
29 T_DECL(waitq_basic, "General waitq test",
30 T_META_RUN_CONCURRENTLY(false))
31 {
32 T_EXPECT_EQ(1ull, run_sysctl_test("waitq_basic", 0), "waitq_basic_test");
33 }
34
35 static const int NPORTS = 1024; /* must be larger than 0x200 */
36 static mach_port_t stress_ports[NPORTS];
37
38 T_DECL(waitq_link_alloc_stress,
39 "General stress test around waitq link allocations")
40 {
41 for (uint32_t i = 0; i < NPORTS; i++) {
42 kern_return_t kr = mach_port_allocate(mach_task_self(),
43 MACH_PORT_RIGHT_RECEIVE, &stress_ports[i]);
44 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "allocate");
45 }
46
47 dispatch_apply(4, DISPATCH_APPLY_AUTO, ^(size_t __i __unused){
48 kern_return_t kr;
49
50 for (int times = 10; times-- > 0;) {
51 mach_port_t pset = MACH_PORT_NULL;
52
53 kr = mach_port_allocate(mach_task_self(),
54 MACH_PORT_RIGHT_PORT_SET, &pset);
55 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc pset");
56
57 for (uint32_t i = 0; i < NPORTS; i++) {
58 kr = mach_port_insert_member(mach_task_self(),
59 stress_ports[i], pset);
60 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "insert_member");
61 }
62
63 for (uint32_t i = 0; i < NPORTS; i++) {
64 kr = mach_port_move_member(mach_task_self(),
65 stress_ports[i], MACH_PORT_NULL);
66 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "insert_member");
67 }
68
69 for (uint32_t i = 0; i < NPORTS; i++) {
70 kr = mach_port_insert_member(mach_task_self(),
71 stress_ports[i], pset);
72 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "insert_member");
73 }
74
75 kr = mach_port_mod_refs(mach_task_self(), pset,
76 MACH_PORT_RIGHT_PORT_SET, -1);
77 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "dealloc pset");
78 }
79 });
80
81 for (uint32_t i = 0; i < NPORTS; i++) {
82 kern_return_t kr = mach_port_destruct(mach_task_self(),
83 stress_ports[i], 0, 0);
84 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "deallocate");
85 }
86
87 T_PASS("the kernel survived");
88 }
89