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