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