xref: /xnu-11417.121.6/tests/mach_eventlink.c (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1*a1e26a70SApple OSS Distributions /*
2*a1e26a70SApple OSS Distributions  * mach eventlink: Tests mach eventlink kernel synchronization primitive.
3*a1e26a70SApple OSS Distributions  */
4*a1e26a70SApple OSS Distributions 
5*a1e26a70SApple OSS Distributions #include <darwintest.h>
6*a1e26a70SApple OSS Distributions #include <darwintest_multiprocess.h>
7*a1e26a70SApple OSS Distributions 
8*a1e26a70SApple OSS Distributions #include <pthread.h>
9*a1e26a70SApple OSS Distributions #include <launch.h>
10*a1e26a70SApple OSS Distributions #include <mach/mach.h>
11*a1e26a70SApple OSS Distributions #include <mach/message.h>
12*a1e26a70SApple OSS Distributions #include <mach/mach_voucher.h>
13*a1e26a70SApple OSS Distributions #include <pthread/workqueue_private.h>
14*a1e26a70SApple OSS Distributions #include <voucher/ipc_pthread_priority_types.h>
15*a1e26a70SApple OSS Distributions #include <servers/bootstrap.h>
16*a1e26a70SApple OSS Distributions #include <stdlib.h>
17*a1e26a70SApple OSS Distributions #include <sys/event.h>
18*a1e26a70SApple OSS Distributions #include <unistd.h>
19*a1e26a70SApple OSS Distributions #include <crt_externs.h>
20*a1e26a70SApple OSS Distributions #include <signal.h>
21*a1e26a70SApple OSS Distributions #include <sys/types.h>
22*a1e26a70SApple OSS Distributions #include <sys/sysctl.h>
23*a1e26a70SApple OSS Distributions #include <libkern/OSAtomic.h>
24*a1e26a70SApple OSS Distributions #include <sys/wait.h>
25*a1e26a70SApple OSS Distributions #include <spawn.h>
26*a1e26a70SApple OSS Distributions #include <spawn_private.h>
27*a1e26a70SApple OSS Distributions #include <mach/mach_eventlink.h>
28*a1e26a70SApple OSS Distributions #include <os/atomic_private.h>
29*a1e26a70SApple OSS Distributions 
30*a1e26a70SApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.mach_eventlink"),
31*a1e26a70SApple OSS Distributions     T_META_RUN_CONCURRENTLY(true));
32*a1e26a70SApple OSS Distributions 
33*a1e26a70SApple OSS Distributions static int g_loop_iterations = 100000;
34*a1e26a70SApple OSS Distributions 
35*a1e26a70SApple OSS Distributions static kern_return_t
test_eventlink_create(mach_port_t * port_pair)36*a1e26a70SApple OSS Distributions test_eventlink_create(mach_port_t *port_pair)
37*a1e26a70SApple OSS Distributions {
38*a1e26a70SApple OSS Distributions 	kern_return_t kr;
39*a1e26a70SApple OSS Distributions 
40*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_create(mach_task_self(), MELC_OPTION_NO_COPYIN, port_pair);
41*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_create");
42*a1e26a70SApple OSS Distributions 
43*a1e26a70SApple OSS Distributions 	return kr;
44*a1e26a70SApple OSS Distributions }
45*a1e26a70SApple OSS Distributions 
46*a1e26a70SApple OSS Distributions static pthread_t
thread_create_for_test(void * (* function)(void *),void * arg)47*a1e26a70SApple OSS Distributions thread_create_for_test(void * (*function)(void *), void *arg)
48*a1e26a70SApple OSS Distributions {
49*a1e26a70SApple OSS Distributions 	pthread_t pthread;
50*a1e26a70SApple OSS Distributions 	pthread_attr_t attr;
51*a1e26a70SApple OSS Distributions 
52*a1e26a70SApple OSS Distributions 	pthread_attr_init(&attr);
53*a1e26a70SApple OSS Distributions 	pthread_create(&pthread, &attr, function, arg);
54*a1e26a70SApple OSS Distributions 
55*a1e26a70SApple OSS Distributions 	T_LOG("pthread created\n");
56*a1e26a70SApple OSS Distributions 	return pthread;
57*a1e26a70SApple OSS Distributions }
58*a1e26a70SApple OSS Distributions 
59*a1e26a70SApple OSS Distributions static void *
while1loop(__unused void * arg)60*a1e26a70SApple OSS Distributions while1loop(__unused void *arg)
61*a1e26a70SApple OSS Distributions {
62*a1e26a70SApple OSS Distributions 	while (1) {
63*a1e26a70SApple OSS Distributions 		;
64*a1e26a70SApple OSS Distributions 	}
65*a1e26a70SApple OSS Distributions 	return NULL;
66*a1e26a70SApple OSS Distributions }
67*a1e26a70SApple OSS Distributions 
68*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_with_timeout(void * arg)69*a1e26a70SApple OSS Distributions test_eventlink_wait_with_timeout(void *arg)
70*a1e26a70SApple OSS Distributions {
71*a1e26a70SApple OSS Distributions 	kern_return_t kr;
72*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
73*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
74*a1e26a70SApple OSS Distributions 	uint64_t ticks = mach_absolute_time();
75*a1e26a70SApple OSS Distributions 	uint64_t count = 1;
76*a1e26a70SApple OSS Distributions 
77*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
78*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
79*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
80*a1e26a70SApple OSS Distributions 
81*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink with timeout */
82*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
83*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, ticks + 5000);
84*a1e26a70SApple OSS Distributions 
85*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_OPERATION_TIMED_OUT, "mach_eventlink_wait_until returned expected error");
86*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)0, "mach_eventlink_wait_until returned correct count value");
87*a1e26a70SApple OSS Distributions 
88*a1e26a70SApple OSS Distributions 	return NULL;
89*a1e26a70SApple OSS Distributions }
90*a1e26a70SApple OSS Distributions 
91*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_no_wait(void * arg)92*a1e26a70SApple OSS Distributions test_eventlink_wait_no_wait(void *arg)
93*a1e26a70SApple OSS Distributions {
94*a1e26a70SApple OSS Distributions 	kern_return_t kr;
95*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
96*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
97*a1e26a70SApple OSS Distributions 	uint64_t count = 1;
98*a1e26a70SApple OSS Distributions 
99*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
100*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
101*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
102*a1e26a70SApple OSS Distributions 
103*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
104*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NO_WAIT,
105*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
106*a1e26a70SApple OSS Distributions 
107*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_OPERATION_TIMED_OUT, "mach_eventlink_wait_until returned expected error");
108*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)0, "mach_eventlink_wait_until returned correct count value");
109*a1e26a70SApple OSS Distributions 
110*a1e26a70SApple OSS Distributions 	return NULL;
111*a1e26a70SApple OSS Distributions }
112*a1e26a70SApple OSS Distributions 
113*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_destroy(void * arg)114*a1e26a70SApple OSS Distributions test_eventlink_wait_destroy(void *arg)
115*a1e26a70SApple OSS Distributions {
116*a1e26a70SApple OSS Distributions 	kern_return_t kr;
117*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
118*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
119*a1e26a70SApple OSS Distributions 	uint64_t count = 1;
120*a1e26a70SApple OSS Distributions 
121*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
122*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
123*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
124*a1e26a70SApple OSS Distributions 
125*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
126*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
127*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
128*a1e26a70SApple OSS Distributions 
129*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_TERMINATED, "mach_eventlink_wait_until returned expected error");
130*a1e26a70SApple OSS Distributions 
131*a1e26a70SApple OSS Distributions 	return NULL;
132*a1e26a70SApple OSS Distributions }
133*a1e26a70SApple OSS Distributions 
134*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_for_signal(void * arg)135*a1e26a70SApple OSS Distributions test_eventlink_wait_for_signal(void *arg)
136*a1e26a70SApple OSS Distributions {
137*a1e26a70SApple OSS Distributions 	kern_return_t kr;
138*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
139*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
140*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
141*a1e26a70SApple OSS Distributions 
142*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
143*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
144*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
145*a1e26a70SApple OSS Distributions 
146*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
147*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
148*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
149*a1e26a70SApple OSS Distributions 
150*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_wait_until");
151*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
152*a1e26a70SApple OSS Distributions 
153*a1e26a70SApple OSS Distributions 	return NULL;
154*a1e26a70SApple OSS Distributions }
155*a1e26a70SApple OSS Distributions 
156*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_then_signal(void * arg)157*a1e26a70SApple OSS Distributions test_eventlink_wait_then_signal(void *arg)
158*a1e26a70SApple OSS Distributions {
159*a1e26a70SApple OSS Distributions 	kern_return_t kr;
160*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
161*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
162*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
163*a1e26a70SApple OSS Distributions 
164*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
165*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
166*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
167*a1e26a70SApple OSS Distributions 
168*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
169*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
170*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
171*a1e26a70SApple OSS Distributions 
172*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_wait_until");
173*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
174*a1e26a70SApple OSS Distributions 
175*a1e26a70SApple OSS Distributions 	/* Signal the eventlink to wakeup other side */
176*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal(eventlink_port, 0);
177*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal");
178*a1e26a70SApple OSS Distributions 
179*a1e26a70SApple OSS Distributions 	return NULL;
180*a1e26a70SApple OSS Distributions }
181*a1e26a70SApple OSS Distributions 
182*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_then_wait_signal_with_no_wait(void * arg)183*a1e26a70SApple OSS Distributions test_eventlink_wait_then_wait_signal_with_no_wait(void *arg)
184*a1e26a70SApple OSS Distributions {
185*a1e26a70SApple OSS Distributions 	kern_return_t kr;
186*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
187*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
188*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
189*a1e26a70SApple OSS Distributions 
190*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
191*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
192*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
193*a1e26a70SApple OSS Distributions 
194*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
195*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
196*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
197*a1e26a70SApple OSS Distributions 
198*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_wait_until");
199*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
200*a1e26a70SApple OSS Distributions 
201*a1e26a70SApple OSS Distributions 	/* Signal wait the eventlink */
202*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(eventlink_port, &count, 0, MELSW_OPTION_NO_WAIT,
203*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
204*a1e26a70SApple OSS Distributions 
205*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_OPERATION_TIMED_OUT, "mach_eventlink_wait_until returned expected error");
206*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
207*a1e26a70SApple OSS Distributions 
208*a1e26a70SApple OSS Distributions 	return NULL;
209*a1e26a70SApple OSS Distributions }
210*a1e26a70SApple OSS Distributions 
211*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_then_wait_signal_with_prepost(void * arg)212*a1e26a70SApple OSS Distributions test_eventlink_wait_then_wait_signal_with_prepost(void *arg)
213*a1e26a70SApple OSS Distributions {
214*a1e26a70SApple OSS Distributions 	kern_return_t kr;
215*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
216*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
217*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
218*a1e26a70SApple OSS Distributions 
219*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
220*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
221*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
222*a1e26a70SApple OSS Distributions 
223*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
224*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
225*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
226*a1e26a70SApple OSS Distributions 
227*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_wait_until");
228*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
229*a1e26a70SApple OSS Distributions 
230*a1e26a70SApple OSS Distributions 	/* Signal wait the eventlink with stale counter value */
231*a1e26a70SApple OSS Distributions 	count = 0;
232*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(eventlink_port, &count, 0, MELSW_OPTION_NONE,
233*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
234*a1e26a70SApple OSS Distributions 
235*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal_wait_until");
236*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
237*a1e26a70SApple OSS Distributions 
238*a1e26a70SApple OSS Distributions 	return NULL;
239*a1e26a70SApple OSS Distributions }
240*a1e26a70SApple OSS Distributions 
241*a1e26a70SApple OSS Distributions static void *
test_eventlink_wait_then_signal_loop(void * arg)242*a1e26a70SApple OSS Distributions test_eventlink_wait_then_signal_loop(void *arg)
243*a1e26a70SApple OSS Distributions {
244*a1e26a70SApple OSS Distributions 	kern_return_t kr;
245*a1e26a70SApple OSS Distributions 	mach_port_t eventlink_port = (mach_port_t) (uintptr_t)arg;
246*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
247*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
248*a1e26a70SApple OSS Distributions 	int i;
249*a1e26a70SApple OSS Distributions 
250*a1e26a70SApple OSS Distributions 	/* Associate thread with eventlink port */
251*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(eventlink_port, self, 0, 0, 0, 0, MELA_OPTION_NONE);
252*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate");
253*a1e26a70SApple OSS Distributions 
254*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink */
255*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_wait_until(eventlink_port, &count, MELSW_OPTION_NONE,
256*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
257*a1e26a70SApple OSS Distributions 
258*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_wait_until");
259*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_wait_until returned correct count value");
260*a1e26a70SApple OSS Distributions 
261*a1e26a70SApple OSS Distributions 	for (i = 1; i < g_loop_iterations; i++) {
262*a1e26a70SApple OSS Distributions 		/* Signal wait the eventlink */
263*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_signal_wait_until(eventlink_port, &count, 0, MELSW_OPTION_NONE,
264*a1e26a70SApple OSS Distributions 		    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
265*a1e26a70SApple OSS Distributions 
266*a1e26a70SApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal_wait_until");
267*a1e26a70SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ(count, (uint64_t)(i + 1), "mach_eventlink_wait_until returned correct count value");
268*a1e26a70SApple OSS Distributions 	}
269*a1e26a70SApple OSS Distributions 
270*a1e26a70SApple OSS Distributions 	/* Signal the eventlink to wakeup other side */
271*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal(eventlink_port, 0);
272*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal");
273*a1e26a70SApple OSS Distributions 
274*a1e26a70SApple OSS Distributions 	return NULL;
275*a1e26a70SApple OSS Distributions }
276*a1e26a70SApple OSS Distributions 
277*a1e26a70SApple OSS Distributions /*
278*a1e26a70SApple OSS Distributions  * Test 1: Create ipc eventlink kernel object.
279*a1e26a70SApple OSS Distributions  *
280*a1e26a70SApple OSS Distributions  * Calls eventlink creates which returns a pair of eventlink port objects.
281*a1e26a70SApple OSS Distributions  */
282*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_create, "eventlink create test", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
283*a1e26a70SApple OSS Distributions {
284*a1e26a70SApple OSS Distributions 	kern_return_t kr;
285*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
286*a1e26a70SApple OSS Distributions 
287*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
288*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
289*a1e26a70SApple OSS Distributions 		return;
290*a1e26a70SApple OSS Distributions 	}
291*a1e26a70SApple OSS Distributions 
292*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
293*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
294*a1e26a70SApple OSS Distributions }
295*a1e26a70SApple OSS Distributions 
296*a1e26a70SApple OSS Distributions /*
297*a1e26a70SApple OSS Distributions  * Test 2: Create ipc eventlink kernel object and call eventlink destroy
298*a1e26a70SApple OSS Distributions  *
299*a1e26a70SApple OSS Distributions  * Calls eventlink creates which returns a pair of eventlink port objects.
300*a1e26a70SApple OSS Distributions  * Calls eventlink destroy on eventlink port pair.
301*a1e26a70SApple OSS Distributions  */
302*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_destroy, "eventlink destroy test", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
303*a1e26a70SApple OSS Distributions {
304*a1e26a70SApple OSS Distributions 	kern_return_t kr;
305*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
306*a1e26a70SApple OSS Distributions 
307*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
308*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
309*a1e26a70SApple OSS Distributions 		return;
310*a1e26a70SApple OSS Distributions 	}
311*a1e26a70SApple OSS Distributions 
312*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_destroy(port_pair[0]);
313*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_destroy");
314*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_destroy(port_pair[1]);
315*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_destroy");
316*a1e26a70SApple OSS Distributions }
317*a1e26a70SApple OSS Distributions 
318*a1e26a70SApple OSS Distributions /*
319*a1e26a70SApple OSS Distributions  * Test 3: Associate threads to eventlink object.
320*a1e26a70SApple OSS Distributions  *
321*a1e26a70SApple OSS Distributions  * Create eventlink object pair and associate threads to each side and then
322*a1e26a70SApple OSS Distributions  * disassociate threads and check for error conditions.
323*a1e26a70SApple OSS Distributions  */
324*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_associate, "eventlink associate test", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
325*a1e26a70SApple OSS Distributions {
326*a1e26a70SApple OSS Distributions 	kern_return_t kr;
327*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
328*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
329*a1e26a70SApple OSS Distributions 	mach_port_t other_thread = MACH_PORT_NULL;
330*a1e26a70SApple OSS Distributions 	pthread_t pthread;
331*a1e26a70SApple OSS Distributions 
332*a1e26a70SApple OSS Distributions 	/* eventlink associate to NULL eventlink object */
333*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(MACH_PORT_NULL, self, 0, 0, 0, 0, MELA_OPTION_NONE);
334*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, MACH_SEND_INVALID_DEST, "mach_eventlink_associate with null eventlink returned expected error");
335*a1e26a70SApple OSS Distributions 
336*a1e26a70SApple OSS Distributions 	/* eventlink disassociate to NULL eventlink object */
337*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_disassociate(MACH_PORT_NULL, MELD_OPTION_NONE);
338*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, MACH_SEND_INVALID_DEST, "mach_eventlink_disassociate with null eventlink returned expected error");
339*a1e26a70SApple OSS Distributions 
340*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
341*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
342*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
343*a1e26a70SApple OSS Distributions 		return;
344*a1e26a70SApple OSS Distributions 	}
345*a1e26a70SApple OSS Distributions 
346*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(while1loop, NULL);
347*a1e26a70SApple OSS Distributions 	other_thread = pthread_mach_thread_np(pthread);
348*a1e26a70SApple OSS Distributions 
349*a1e26a70SApple OSS Distributions 	for (int i = 0; i < 3; i++) {
350*a1e26a70SApple OSS Distributions 		/* Associate thread to eventlink objects */
351*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_associate(port_pair[0], self, 0, 0, 0, 0, MELA_OPTION_NONE);
352*a1e26a70SApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 1");
353*a1e26a70SApple OSS Distributions 
354*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_associate(port_pair[1], other_thread, 0, 0, 0, 0, MELA_OPTION_NONE);
355*a1e26a70SApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
356*a1e26a70SApple OSS Distributions 
357*a1e26a70SApple OSS Distributions 		/* Try to associate again with diff threads, expect failure */
358*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_associate(port_pair[0], other_thread, 0, 0, 0, 0, MELA_OPTION_NONE);
359*a1e26a70SApple OSS Distributions 		T_EXPECT_MACH_ERROR(kr, KERN_NAME_EXISTS, "mach_eventlink_associate for associated "
360*a1e26a70SApple OSS Distributions 		    "objects returned expected error");
361*a1e26a70SApple OSS Distributions 
362*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
363*a1e26a70SApple OSS Distributions 		T_EXPECT_MACH_ERROR(kr, KERN_NAME_EXISTS, "mach_eventlink_associate for associated "
364*a1e26a70SApple OSS Distributions 		    "objects return expected error");
365*a1e26a70SApple OSS Distributions 
366*a1e26a70SApple OSS Distributions 		/* Try to disassociate the threads */
367*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_disassociate(port_pair[0], MELD_OPTION_NONE);
368*a1e26a70SApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_disassociate for object 1");
369*a1e26a70SApple OSS Distributions 
370*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_disassociate(port_pair[1], MELD_OPTION_NONE);
371*a1e26a70SApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_disassociate for object 2");
372*a1e26a70SApple OSS Distributions 
373*a1e26a70SApple OSS Distributions 		/* Try to disassociate the threads again, expect failure */
374*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_disassociate(port_pair[0], MELD_OPTION_NONE);
375*a1e26a70SApple OSS Distributions 		T_EXPECT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "mach_eventlink_disassociate for "
376*a1e26a70SApple OSS Distributions 		    "disassociated objects returned expected error");
377*a1e26a70SApple OSS Distributions 
378*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_disassociate(port_pair[1], MELD_OPTION_NONE);
379*a1e26a70SApple OSS Distributions 		T_EXPECT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "mach_eventlink_disassociate for "
380*a1e26a70SApple OSS Distributions 		    "disassociated objects returned expected error");
381*a1e26a70SApple OSS Distributions 	}
382*a1e26a70SApple OSS Distributions 
383*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_destroy(port_pair[0]);
384*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_destroy");
385*a1e26a70SApple OSS Distributions 
386*a1e26a70SApple OSS Distributions 	/* Try disassociate on other end of destoryed eventlink pair */
387*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_disassociate(port_pair[1], MELD_OPTION_NONE);
388*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_TERMINATED, "mach_eventlink_disassociate for "
389*a1e26a70SApple OSS Distributions 	    "terminated object returned expected error");
390*a1e26a70SApple OSS Distributions 
391*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_destroy(port_pair[1]);
392*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_destroy");
393*a1e26a70SApple OSS Distributions }
394*a1e26a70SApple OSS Distributions 
395*a1e26a70SApple OSS Distributions /*
396*a1e26a70SApple OSS Distributions  * Test 4: Test eventlink wait with timeout.
397*a1e26a70SApple OSS Distributions  *
398*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test eventlink wait with timeout.
399*a1e26a70SApple OSS Distributions  */
400*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_timeout, "eventlink wait timeout test", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
401*a1e26a70SApple OSS Distributions {
402*a1e26a70SApple OSS Distributions 	kern_return_t kr;
403*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
404*a1e26a70SApple OSS Distributions 	pthread_t pthread;
405*a1e26a70SApple OSS Distributions 
406*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
407*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
408*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
409*a1e26a70SApple OSS Distributions 		return;
410*a1e26a70SApple OSS Distributions 	}
411*a1e26a70SApple OSS Distributions 
412*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_with_timeout, (void *)(uintptr_t)port_pair[0]);
413*a1e26a70SApple OSS Distributions 	sleep(10);
414*a1e26a70SApple OSS Distributions 
415*a1e26a70SApple OSS Distributions 	/* destroy the eventlink object, the wake status of thread will check if the test passsed or failed */
416*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
417*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
418*a1e26a70SApple OSS Distributions 
419*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
420*a1e26a70SApple OSS Distributions }
421*a1e26a70SApple OSS Distributions 
422*a1e26a70SApple OSS Distributions /*
423*a1e26a70SApple OSS Distributions  * Test 5: Test eventlink wait with no wait.
424*a1e26a70SApple OSS Distributions  *
425*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test eventlink wait with no wait flag.
426*a1e26a70SApple OSS Distributions  */
427*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_no_wait, "eventlink wait no wait test", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
428*a1e26a70SApple OSS Distributions {
429*a1e26a70SApple OSS Distributions 	kern_return_t kr;
430*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
431*a1e26a70SApple OSS Distributions 	pthread_t pthread;
432*a1e26a70SApple OSS Distributions 
433*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
434*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
435*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
436*a1e26a70SApple OSS Distributions 		return;
437*a1e26a70SApple OSS Distributions 	}
438*a1e26a70SApple OSS Distributions 
439*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_no_wait, (void *)(uintptr_t)port_pair[0]);
440*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
441*a1e26a70SApple OSS Distributions 
442*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
443*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
444*a1e26a70SApple OSS Distributions }
445*a1e26a70SApple OSS Distributions 
446*a1e26a70SApple OSS Distributions /*
447*a1e26a70SApple OSS Distributions  * Test 6: Test eventlink wait and destroy.
448*a1e26a70SApple OSS Distributions  *
449*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and destroy the port.
450*a1e26a70SApple OSS Distributions  */
451*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_and_destroy, "eventlink wait and destroy", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
452*a1e26a70SApple OSS Distributions {
453*a1e26a70SApple OSS Distributions 	kern_return_t kr;
454*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
455*a1e26a70SApple OSS Distributions 	pthread_t pthread;
456*a1e26a70SApple OSS Distributions 
457*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
458*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
459*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
460*a1e26a70SApple OSS Distributions 		return;
461*a1e26a70SApple OSS Distributions 	}
462*a1e26a70SApple OSS Distributions 
463*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_destroy, (void *)(uintptr_t)port_pair[0]);
464*a1e26a70SApple OSS Distributions 
465*a1e26a70SApple OSS Distributions 	sleep(5);
466*a1e26a70SApple OSS Distributions 
467*a1e26a70SApple OSS Distributions 	/* Increase the send right count for port before destroy to make sure no sender does not fire on destroy */
468*a1e26a70SApple OSS Distributions 	kr = mach_port_mod_refs(mach_task_self(), port_pair[0], MACH_PORT_RIGHT_SEND, 2);
469*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_mod_refs");
470*a1e26a70SApple OSS Distributions 
471*a1e26a70SApple OSS Distributions 	/* Destroy the port for thread to wakeup */
472*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_destroy(port_pair[0]);
473*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_destroy");
474*a1e26a70SApple OSS Distributions 
475*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
476*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
477*a1e26a70SApple OSS Distributions }
478*a1e26a70SApple OSS Distributions 
479*a1e26a70SApple OSS Distributions 
480*a1e26a70SApple OSS Distributions /*
481*a1e26a70SApple OSS Distributions  * Test 7: Test eventlink wait and destroy remote side.
482*a1e26a70SApple OSS Distributions  *
483*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads, wait and destroy the remote eventlink port.
484*a1e26a70SApple OSS Distributions  */
485*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_and_destroy_remote, "eventlink wait and remote destroy", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
486*a1e26a70SApple OSS Distributions {
487*a1e26a70SApple OSS Distributions 	kern_return_t kr;
488*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
489*a1e26a70SApple OSS Distributions 	pthread_t pthread;
490*a1e26a70SApple OSS Distributions 
491*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
492*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
493*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
494*a1e26a70SApple OSS Distributions 		return;
495*a1e26a70SApple OSS Distributions 	}
496*a1e26a70SApple OSS Distributions 
497*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_destroy, (void *)(uintptr_t)port_pair[0]);
498*a1e26a70SApple OSS Distributions 
499*a1e26a70SApple OSS Distributions 	sleep(5);
500*a1e26a70SApple OSS Distributions 
501*a1e26a70SApple OSS Distributions 	/* Increase the send right count for port before destroy to make sure no sender does not fire on destroy */
502*a1e26a70SApple OSS Distributions 	kr = mach_port_mod_refs(mach_task_self(), port_pair[1], MACH_PORT_RIGHT_SEND, 2);
503*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_mod_refs");
504*a1e26a70SApple OSS Distributions 
505*a1e26a70SApple OSS Distributions 	/* Destroy the port for thread to wakeup */
506*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_destroy(port_pair[1]);
507*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_destroy");
508*a1e26a70SApple OSS Distributions 
509*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
510*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
511*a1e26a70SApple OSS Distributions }
512*a1e26a70SApple OSS Distributions 
513*a1e26a70SApple OSS Distributions /*
514*a1e26a70SApple OSS Distributions  * Test 8: Test eventlink wait and deallocate port.
515*a1e26a70SApple OSS Distributions  *
516*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads, wait and deallocate the eventlink port.
517*a1e26a70SApple OSS Distributions  */
518*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_and_deallocate, "eventlink wait and deallocate", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
519*a1e26a70SApple OSS Distributions {
520*a1e26a70SApple OSS Distributions 	kern_return_t kr;
521*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
522*a1e26a70SApple OSS Distributions 	pthread_t pthread;
523*a1e26a70SApple OSS Distributions 
524*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
525*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
526*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
527*a1e26a70SApple OSS Distributions 		return;
528*a1e26a70SApple OSS Distributions 	}
529*a1e26a70SApple OSS Distributions 
530*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_destroy, (void *)(uintptr_t)port_pair[0]);
531*a1e26a70SApple OSS Distributions 
532*a1e26a70SApple OSS Distributions 	sleep(5);
533*a1e26a70SApple OSS Distributions 
534*a1e26a70SApple OSS Distributions 	/* Destroy the port for thread to wakeup */
535*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
536*a1e26a70SApple OSS Distributions 
537*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
538*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
539*a1e26a70SApple OSS Distributions }
540*a1e26a70SApple OSS Distributions 
541*a1e26a70SApple OSS Distributions /*
542*a1e26a70SApple OSS Distributions  * Test 9: Test eventlink wait and disassociate.
543*a1e26a70SApple OSS Distributions  *
544*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads, wait and disassociate thread from the eventlink port.
545*a1e26a70SApple OSS Distributions  */
546*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_and_disassociate, "eventlink wait and disassociate", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
547*a1e26a70SApple OSS Distributions {
548*a1e26a70SApple OSS Distributions 	kern_return_t kr;
549*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
550*a1e26a70SApple OSS Distributions 	pthread_t pthread;
551*a1e26a70SApple OSS Distributions 
552*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
553*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
554*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
555*a1e26a70SApple OSS Distributions 		return;
556*a1e26a70SApple OSS Distributions 	}
557*a1e26a70SApple OSS Distributions 
558*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_destroy, (void *)(uintptr_t)port_pair[0]);
559*a1e26a70SApple OSS Distributions 
560*a1e26a70SApple OSS Distributions 	sleep(5);
561*a1e26a70SApple OSS Distributions 
562*a1e26a70SApple OSS Distributions 	/* Disassociate thread from eventlink for thread to wakeup */
563*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_disassociate(port_pair[0], MELD_OPTION_NONE);
564*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_disassociate");
565*a1e26a70SApple OSS Distributions 
566*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
567*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
568*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
569*a1e26a70SApple OSS Distributions }
570*a1e26a70SApple OSS Distributions 
571*a1e26a70SApple OSS Distributions /*
572*a1e26a70SApple OSS Distributions  * Test 10: Test eventlink wait and signal.
573*a1e26a70SApple OSS Distributions  *
574*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test wait signal.
575*a1e26a70SApple OSS Distributions  */
576*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_and_signal, "eventlink wait and signal", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
577*a1e26a70SApple OSS Distributions {
578*a1e26a70SApple OSS Distributions 	kern_return_t kr;
579*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
580*a1e26a70SApple OSS Distributions 	pthread_t pthread;
581*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
582*a1e26a70SApple OSS Distributions 
583*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
584*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
585*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
586*a1e26a70SApple OSS Distributions 		return;
587*a1e26a70SApple OSS Distributions 	}
588*a1e26a70SApple OSS Distributions 
589*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_for_signal, (void *)(uintptr_t)port_pair[0]);
590*a1e26a70SApple OSS Distributions 
591*a1e26a70SApple OSS Distributions 	sleep(5);
592*a1e26a70SApple OSS Distributions 
593*a1e26a70SApple OSS Distributions 	/* Associate thread and signal the eventlink */
594*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
595*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
596*a1e26a70SApple OSS Distributions 
597*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal(port_pair[1], 0);
598*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal for object 2");
599*a1e26a70SApple OSS Distributions 
600*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
601*a1e26a70SApple OSS Distributions 
602*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
603*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
604*a1e26a70SApple OSS Distributions }
605*a1e26a70SApple OSS Distributions 
606*a1e26a70SApple OSS Distributions /*
607*a1e26a70SApple OSS Distributions  * Test 11: Test eventlink wait_signal.
608*a1e26a70SApple OSS Distributions  *
609*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test wait_signal.
610*a1e26a70SApple OSS Distributions  */
611*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_signal, "eventlink wait_signal", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
612*a1e26a70SApple OSS Distributions {
613*a1e26a70SApple OSS Distributions 	kern_return_t kr;
614*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
615*a1e26a70SApple OSS Distributions 	pthread_t pthread;
616*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
617*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
618*a1e26a70SApple OSS Distributions 
619*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
620*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
621*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
622*a1e26a70SApple OSS Distributions 		return;
623*a1e26a70SApple OSS Distributions 	}
624*a1e26a70SApple OSS Distributions 
625*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_then_signal, (void *)(uintptr_t)port_pair[0]);
626*a1e26a70SApple OSS Distributions 
627*a1e26a70SApple OSS Distributions 	sleep(5);
628*a1e26a70SApple OSS Distributions 
629*a1e26a70SApple OSS Distributions 	/* Associate thread and wait_signal the eventlink */
630*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
631*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
632*a1e26a70SApple OSS Distributions 
633*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink with timeout */
634*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
635*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
636*a1e26a70SApple OSS Distributions 
637*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal_wait_until");
638*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_signal_wait_until returned correct count value");
639*a1e26a70SApple OSS Distributions 
640*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
641*a1e26a70SApple OSS Distributions 
642*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
643*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
644*a1e26a70SApple OSS Distributions }
645*a1e26a70SApple OSS Distributions 
646*a1e26a70SApple OSS Distributions /*
647*a1e26a70SApple OSS Distributions  * Test 12: Test eventlink wait_signal with no wait.
648*a1e26a70SApple OSS Distributions  *
649*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test wait_signal with no wait.
650*a1e26a70SApple OSS Distributions  */
651*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_signal_no_wait, "eventlink wait_signal with no wait", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
652*a1e26a70SApple OSS Distributions {
653*a1e26a70SApple OSS Distributions 	kern_return_t kr;
654*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
655*a1e26a70SApple OSS Distributions 	pthread_t pthread;
656*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
657*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
658*a1e26a70SApple OSS Distributions 
659*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
660*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
661*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
662*a1e26a70SApple OSS Distributions 		return;
663*a1e26a70SApple OSS Distributions 	}
664*a1e26a70SApple OSS Distributions 
665*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_then_wait_signal_with_no_wait, (void *)(uintptr_t)port_pair[0]);
666*a1e26a70SApple OSS Distributions 
667*a1e26a70SApple OSS Distributions 	sleep(5);
668*a1e26a70SApple OSS Distributions 
669*a1e26a70SApple OSS Distributions 	/* Associate thread and wait_signal the eventlink */
670*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
671*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
672*a1e26a70SApple OSS Distributions 
673*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink with timeout */
674*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
675*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
676*a1e26a70SApple OSS Distributions 
677*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal_wait_until");
678*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_signal_wait_until returned correct count value");
679*a1e26a70SApple OSS Distributions 
680*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
681*a1e26a70SApple OSS Distributions 
682*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
683*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
684*a1e26a70SApple OSS Distributions }
685*a1e26a70SApple OSS Distributions 
686*a1e26a70SApple OSS Distributions /*
687*a1e26a70SApple OSS Distributions  * Test 13: Test eventlink wait_signal with prepost.
688*a1e26a70SApple OSS Distributions  *
689*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test wait_signal with prepost.
690*a1e26a70SApple OSS Distributions  */
691*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_signal_prepost, "eventlink wait_signal with prepost", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
692*a1e26a70SApple OSS Distributions {
693*a1e26a70SApple OSS Distributions 	kern_return_t kr;
694*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
695*a1e26a70SApple OSS Distributions 	pthread_t pthread;
696*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
697*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
698*a1e26a70SApple OSS Distributions 
699*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
700*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
701*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
702*a1e26a70SApple OSS Distributions 		return;
703*a1e26a70SApple OSS Distributions 	}
704*a1e26a70SApple OSS Distributions 
705*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_then_wait_signal_with_prepost, (void *)(uintptr_t)port_pair[0]);
706*a1e26a70SApple OSS Distributions 
707*a1e26a70SApple OSS Distributions 	sleep(5);
708*a1e26a70SApple OSS Distributions 
709*a1e26a70SApple OSS Distributions 	/* Associate thread and wait_signal the eventlink */
710*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
711*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
712*a1e26a70SApple OSS Distributions 
713*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink with timeout */
714*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
715*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
716*a1e26a70SApple OSS Distributions 
717*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal_wait_until");
718*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_signal_wait_until returned correct count value");
719*a1e26a70SApple OSS Distributions 
720*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
721*a1e26a70SApple OSS Distributions 
722*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
723*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
724*a1e26a70SApple OSS Distributions }
725*a1e26a70SApple OSS Distributions 
726*a1e26a70SApple OSS Distributions /*
727*a1e26a70SApple OSS Distributions  * Test 14: Test eventlink wait_signal with associate on wait option.
728*a1e26a70SApple OSS Distributions  *
729*a1e26a70SApple OSS Distributions  * Create an eventlink object, set associate on wait on one side and test wait_signal.
730*a1e26a70SApple OSS Distributions  */
731*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_signal_associate_on_wait, "eventlink wait_signal associate on wait", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
732*a1e26a70SApple OSS Distributions {
733*a1e26a70SApple OSS Distributions 	kern_return_t kr;
734*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
735*a1e26a70SApple OSS Distributions 	pthread_t pthread;
736*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
737*a1e26a70SApple OSS Distributions 
738*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
739*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
740*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
741*a1e26a70SApple OSS Distributions 		return;
742*a1e26a70SApple OSS Distributions 	}
743*a1e26a70SApple OSS Distributions 
744*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_then_signal, (void *)(uintptr_t)port_pair[0]);
745*a1e26a70SApple OSS Distributions 
746*a1e26a70SApple OSS Distributions 	sleep(5);
747*a1e26a70SApple OSS Distributions 
748*a1e26a70SApple OSS Distributions 	/* Set associate on wait and wait_signal the eventlink */
749*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], MACH_PORT_NULL, 0, 0, 0, 0, MELA_OPTION_ASSOCIATE_ON_WAIT);
750*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate with associate on wait for object 2");
751*a1e26a70SApple OSS Distributions 
752*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink with timeout */
753*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
754*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
755*a1e26a70SApple OSS Distributions 
756*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_signal_wait_until");
757*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(count, (uint64_t)1, "mach_eventlink_signal_wait_until returned correct count value");
758*a1e26a70SApple OSS Distributions 
759*a1e26a70SApple OSS Distributions 	/* Remove associate on wait option */
760*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_disassociate(port_pair[1], MELD_OPTION_NONE);
761*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_disassociate");
762*a1e26a70SApple OSS Distributions 
763*a1e26a70SApple OSS Distributions 	/* Wait on the eventlink with timeout */
764*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
765*a1e26a70SApple OSS Distributions 	    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
766*a1e26a70SApple OSS Distributions 
767*a1e26a70SApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "mach_eventlink_wait_until returned expected error");
768*a1e26a70SApple OSS Distributions 
769*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
770*a1e26a70SApple OSS Distributions 
771*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
772*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
773*a1e26a70SApple OSS Distributions }
774*a1e26a70SApple OSS Distributions 
775*a1e26a70SApple OSS Distributions /*
776*a1e26a70SApple OSS Distributions  * Test 15: Test eventlink wait_signal_loop.
777*a1e26a70SApple OSS Distributions  *
778*a1e26a70SApple OSS Distributions  * Create an eventlink object, associate threads and test wait_signal in a loop.
779*a1e26a70SApple OSS Distributions  */
780*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_signal_loop, "eventlink wait_signal in loop", T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
781*a1e26a70SApple OSS Distributions {
782*a1e26a70SApple OSS Distributions 	kern_return_t kr;
783*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
784*a1e26a70SApple OSS Distributions 	pthread_t pthread;
785*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
786*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
787*a1e26a70SApple OSS Distributions 	int i;
788*a1e26a70SApple OSS Distributions 
789*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
790*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
791*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
792*a1e26a70SApple OSS Distributions 		return;
793*a1e26a70SApple OSS Distributions 	}
794*a1e26a70SApple OSS Distributions 
795*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_then_signal_loop, (void *)(uintptr_t)port_pair[0]);
796*a1e26a70SApple OSS Distributions 
797*a1e26a70SApple OSS Distributions 	/* Associate thread and wait_signal the eventlink */
798*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
799*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
800*a1e26a70SApple OSS Distributions 
801*a1e26a70SApple OSS Distributions 	for (i = 0; i < g_loop_iterations; i++) {
802*a1e26a70SApple OSS Distributions 		/* Wait on the eventlink with timeout */
803*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
804*a1e26a70SApple OSS Distributions 		    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
805*a1e26a70SApple OSS Distributions 
806*a1e26a70SApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "main thread: mach_eventlink_signal_wait_until");
807*a1e26a70SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ(count, (uint64_t)(i + 1), "main thread: mach_eventlink_signal_wait_until returned correct count value");
808*a1e26a70SApple OSS Distributions 	}
809*a1e26a70SApple OSS Distributions 
810*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
811*a1e26a70SApple OSS Distributions 
812*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
813*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
814*a1e26a70SApple OSS Distributions }
815*a1e26a70SApple OSS Distributions 
816*a1e26a70SApple OSS Distributions 
817*a1e26a70SApple OSS Distributions static uint64_t
nanos_to_abs(uint64_t nanos)818*a1e26a70SApple OSS Distributions nanos_to_abs(uint64_t nanos)
819*a1e26a70SApple OSS Distributions {
820*a1e26a70SApple OSS Distributions 	static mach_timebase_info_data_t timebase_info;
821*a1e26a70SApple OSS Distributions 	mach_timebase_info(&timebase_info);
822*a1e26a70SApple OSS Distributions 	return nanos * timebase_info.denom / timebase_info.numer;
823*a1e26a70SApple OSS Distributions }
824*a1e26a70SApple OSS Distributions 
825*a1e26a70SApple OSS Distributions static const uint64_t DEFAULT_INTERVAL_NS = 15000000; // 15 ms
826*a1e26a70SApple OSS Distributions 
827*a1e26a70SApple OSS Distributions static void
set_realtime(pthread_t thread,uint64_t interval_nanos)828*a1e26a70SApple OSS Distributions set_realtime(pthread_t thread, uint64_t interval_nanos)
829*a1e26a70SApple OSS Distributions {
830*a1e26a70SApple OSS Distributions 	kern_return_t kr;
831*a1e26a70SApple OSS Distributions 	thread_time_constraint_policy_data_t pol;
832*a1e26a70SApple OSS Distributions 
833*a1e26a70SApple OSS Distributions 	mach_port_t target_thread = pthread_mach_thread_np(thread);
834*a1e26a70SApple OSS Distributions 	T_QUIET; T_ASSERT_GT(target_thread, 0, "pthread_mach_thread_np");
835*a1e26a70SApple OSS Distributions 
836*a1e26a70SApple OSS Distributions 	/* 1s 100ms 10ms */
837*a1e26a70SApple OSS Distributions 	pol.period      = (uint32_t)nanos_to_abs(interval_nanos);
838*a1e26a70SApple OSS Distributions 	pol.constraint  = (uint32_t)nanos_to_abs(interval_nanos);
839*a1e26a70SApple OSS Distributions 	pol.computation = (uint32_t)nanos_to_abs(interval_nanos - 1000000); // 1 ms of leeway
840*a1e26a70SApple OSS Distributions 
841*a1e26a70SApple OSS Distributions 	pol.preemptible = 0; /* Ignored by OS */
842*a1e26a70SApple OSS Distributions 	kr = thread_policy_set(target_thread, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) &pol,
843*a1e26a70SApple OSS Distributions 	    THREAD_TIME_CONSTRAINT_POLICY_COUNT);
844*a1e26a70SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "thread_policy_set(THREAD_TIME_CONSTRAINT_POLICY)");
845*a1e26a70SApple OSS Distributions }
846*a1e26a70SApple OSS Distributions 
847*a1e26a70SApple OSS Distributions 
848*a1e26a70SApple OSS Distributions static _Atomic bool suspend_resume_thread_stop = false;
849*a1e26a70SApple OSS Distributions 
850*a1e26a70SApple OSS Distributions static void *
test_suspend_resume_thread(void * arg)851*a1e26a70SApple OSS Distributions test_suspend_resume_thread(void *arg)
852*a1e26a70SApple OSS Distributions {
853*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
854*a1e26a70SApple OSS Distributions 	mach_port_t suspend_resume_other_thread_port = (mach_port_t) (uintptr_t)arg;
855*a1e26a70SApple OSS Distributions 	kern_return_t kr1 = KERN_SUCCESS, kr2 = KERN_SUCCESS;
856*a1e26a70SApple OSS Distributions 
857*a1e26a70SApple OSS Distributions 	while (!os_atomic_load(&suspend_resume_thread_stop, relaxed) && kr1 == KERN_SUCCESS && kr2 == KERN_SUCCESS) {
858*a1e26a70SApple OSS Distributions 		kr1 = thread_suspend(suspend_resume_other_thread_port);
859*a1e26a70SApple OSS Distributions 		kr2 = thread_resume(suspend_resume_other_thread_port);
860*a1e26a70SApple OSS Distributions 		count++;
861*a1e26a70SApple OSS Distributions 	}
862*a1e26a70SApple OSS Distributions 
863*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr1, "thread_suspend #%lld", count);
864*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr2, "thread_resume #%lld", count);
865*a1e26a70SApple OSS Distributions 
866*a1e26a70SApple OSS Distributions 	return NULL;
867*a1e26a70SApple OSS Distributions }
868*a1e26a70SApple OSS Distributions 
869*a1e26a70SApple OSS Distributions /*
870*a1e26a70SApple OSS Distributions  * Test 16: Test suspension of a thread in the middle of a wait-signal operation
871*a1e26a70SApple OSS Distributions  * rdar://120761588 rdar://123887338
872*a1e26a70SApple OSS Distributions  */
873*a1e26a70SApple OSS Distributions T_DECL(test_eventlink_wait_signal_suspend_loop, "eventlink wait_signal + thread_suspend/resume in loop", T_META_ASROOT(YES))
874*a1e26a70SApple OSS Distributions {
875*a1e26a70SApple OSS Distributions 	kern_return_t kr;
876*a1e26a70SApple OSS Distributions 	mach_port_t port_pair[2];
877*a1e26a70SApple OSS Distributions 	pthread_t pthread, suspend_thread;
878*a1e26a70SApple OSS Distributions 	mach_port_t self = mach_thread_self();
879*a1e26a70SApple OSS Distributions 	uint64_t count = 0;
880*a1e26a70SApple OSS Distributions 	int i;
881*a1e26a70SApple OSS Distributions 
882*a1e26a70SApple OSS Distributions 	/* Create an eventlink and associate threads to it */
883*a1e26a70SApple OSS Distributions 	kr = test_eventlink_create(port_pair);
884*a1e26a70SApple OSS Distributions 	if (kr != KERN_SUCCESS) {
885*a1e26a70SApple OSS Distributions 		return;
886*a1e26a70SApple OSS Distributions 	}
887*a1e26a70SApple OSS Distributions 
888*a1e26a70SApple OSS Distributions 	pthread = thread_create_for_test(test_eventlink_wait_then_signal_loop, (void *)(uintptr_t)port_pair[0]);
889*a1e26a70SApple OSS Distributions 	mach_port_t suspend_resume_other_thread_port = pthread_mach_thread_np(pthread);
890*a1e26a70SApple OSS Distributions 
891*a1e26a70SApple OSS Distributions 	/*
892*a1e26a70SApple OSS Distributions 	 * Threads must be RT to get direct handoff mode.
893*a1e26a70SApple OSS Distributions 	 */
894*a1e26a70SApple OSS Distributions 	set_realtime(pthread_self(), DEFAULT_INTERVAL_NS);
895*a1e26a70SApple OSS Distributions 	set_realtime(pthread, DEFAULT_INTERVAL_NS);
896*a1e26a70SApple OSS Distributions 
897*a1e26a70SApple OSS Distributions 	suspend_thread = thread_create_for_test(test_suspend_resume_thread, (void *)(uintptr_t)suspend_resume_other_thread_port);
898*a1e26a70SApple OSS Distributions 
899*a1e26a70SApple OSS Distributions 	/* Associate thread and wait_signal the eventlink */
900*a1e26a70SApple OSS Distributions 	kr = mach_eventlink_associate(port_pair[1], self, 0, 0, 0, 0, MELA_OPTION_NONE);
901*a1e26a70SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_eventlink_associate for object 2");
902*a1e26a70SApple OSS Distributions 
903*a1e26a70SApple OSS Distributions 	for (i = 0; i < g_loop_iterations; i++) {
904*a1e26a70SApple OSS Distributions 		/* Wait on the eventlink with timeout */
905*a1e26a70SApple OSS Distributions 		kr = mach_eventlink_signal_wait_until(port_pair[1], &count, 0, MELSW_OPTION_NONE,
906*a1e26a70SApple OSS Distributions 		    KERN_CLOCK_MACH_ABSOLUTE_TIME, 0);
907*a1e26a70SApple OSS Distributions 
908*a1e26a70SApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "main thread: mach_eventlink_signal_wait_until");
909*a1e26a70SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ(count, (uint64_t)(i + 1), "main thread: mach_eventlink_signal_wait_until returned correct count value");
910*a1e26a70SApple OSS Distributions 	}
911*a1e26a70SApple OSS Distributions 
912*a1e26a70SApple OSS Distributions 	os_atomic_store(&suspend_resume_thread_stop, true, relaxed);
913*a1e26a70SApple OSS Distributions 
914*a1e26a70SApple OSS Distributions 	pthread_join(suspend_thread, NULL);
915*a1e26a70SApple OSS Distributions 	pthread_join(pthread, NULL);
916*a1e26a70SApple OSS Distributions 
917*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[0]);
918*a1e26a70SApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port_pair[1]);
919*a1e26a70SApple OSS Distributions }
920