]> git.saurik.com Git - apple/xnu.git/blame - tests/mach_eventlink.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / tests / mach_eventlink.c
CommitLineData
f427ee49
A
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
29T_GLOBAL_META(T_META_NAMESPACE("xnu.mach_eventlink"),
30 T_META_RUN_CONCURRENTLY(true));
31
32static kern_return_t
33test_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
43static pthread_t
44thread_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
56static void *
57while1loop(void *arg)
58{
59 arg = NULL;
60 while (1) {
61 ;
62 }
63 return NULL;
64}
65
66static void *
67test_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
89static void *
90test_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
111static void *
112test_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
132static void *
133test_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
154static void *
155test_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
180static void *
181test_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
209static void *
210test_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
239static void *
240test_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 */
280T_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 */
300T_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 */
322T_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 */
398T_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 */
425T_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 */
449T_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 */
483T_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 */
516T_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 */
544T_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 */
574T_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 */
609T_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 */
649T_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 */
689T_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 */
729T_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 */
778T_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}