xref: /xnu-8019.80.24/tests/ipc/waitq.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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