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