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