xref: /xnu-12377.61.12/tests/kevent_qos.c (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1*4d495c6eSApple OSS Distributions /*
2*4d495c6eSApple OSS Distributions  * kevent_qos: Tests Synchronous IPC QOS override.
3*4d495c6eSApple OSS Distributions  */
4*4d495c6eSApple OSS Distributions 
5*4d495c6eSApple OSS Distributions #ifdef T_NAMESPACE
6*4d495c6eSApple OSS Distributions #undef T_NAMESPACE
7*4d495c6eSApple OSS Distributions #endif
8*4d495c6eSApple OSS Distributions 
9*4d495c6eSApple OSS Distributions #include <darwintest.h>
10*4d495c6eSApple OSS Distributions #include <darwintest_multiprocess.h>
11*4d495c6eSApple OSS Distributions 
12*4d495c6eSApple OSS Distributions #include <dispatch/dispatch.h>
13*4d495c6eSApple OSS Distributions #include <pthread.h>
14*4d495c6eSApple OSS Distributions #include <launch.h>
15*4d495c6eSApple OSS Distributions #include <mach/mach.h>
16*4d495c6eSApple OSS Distributions #include <mach/message.h>
17*4d495c6eSApple OSS Distributions #include <mach/mach_voucher.h>
18*4d495c6eSApple OSS Distributions #include <pthread/workqueue_private.h>
19*4d495c6eSApple OSS Distributions #include <voucher/ipc_pthread_priority_types.h>
20*4d495c6eSApple OSS Distributions #include <servers/bootstrap.h>
21*4d495c6eSApple OSS Distributions #include <stdlib.h>
22*4d495c6eSApple OSS Distributions #include <sys/event.h>
23*4d495c6eSApple OSS Distributions #include <unistd.h>
24*4d495c6eSApple OSS Distributions #include <crt_externs.h>
25*4d495c6eSApple OSS Distributions #include <mach/mach_port.h>
26*4d495c6eSApple OSS Distributions #include <mach/mach_sync_ipc.h>
27*4d495c6eSApple OSS Distributions 
28*4d495c6eSApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.kevent_qos"),
29*4d495c6eSApple OSS Distributions     T_META_RADAR_COMPONENT_NAME("xnu"),
30*4d495c6eSApple OSS Distributions     T_META_RADAR_COMPONENT_VERSION("kevent"));
31*4d495c6eSApple OSS Distributions 
32*4d495c6eSApple OSS Distributions #define ARRAYLEN(arr) (sizeof(arr) / sizeof(arr[0]))
33*4d495c6eSApple OSS Distributions 
34*4d495c6eSApple OSS Distributions #define INTERMITTENT_TIMEOUT_SEC (3)
35*4d495c6eSApple OSS Distributions #define RECV_TIMEOUT_SECS   (4)
36*4d495c6eSApple OSS Distributions #define SEND_TIMEOUT_SECS   (6)
37*4d495c6eSApple OSS Distributions #define HELPER_TIMEOUT_SECS (15)
38*4d495c6eSApple OSS Distributions 
39*4d495c6eSApple OSS Distributions #define ENV_VAR_QOS (3)
40*4d495c6eSApple OSS Distributions static const char *qos_env[ENV_VAR_QOS] = {"XNU_TEST_QOS_BO", "XNU_TEST_QOS_QO", "XNU_TEST_QOS_AO"};
41*4d495c6eSApple OSS Distributions static const char *qos_name_env[ENV_VAR_QOS] = {"XNU_TEST_QOS_NAME_BO", "XNU_TEST_QOS_NAME_QO", "XNU_TEST_QOS_NAME_AO"};
42*4d495c6eSApple OSS Distributions 
43*4d495c6eSApple OSS Distributions #define ENV_VAR_FUNCTION (1)
44*4d495c6eSApple OSS Distributions static const char *wl_function_name = "XNU_TEST_WL_FUNCTION";
45*4d495c6eSApple OSS Distributions 
46*4d495c6eSApple OSS Distributions static qos_class_t g_expected_qos[ENV_VAR_QOS];
47*4d495c6eSApple OSS Distributions static const char *g_expected_qos_name[ENV_VAR_QOS];
48*4d495c6eSApple OSS Distributions 
49*4d495c6eSApple OSS Distributions #define ENV_QOS_BEFORE_OVERRIDE (0)
50*4d495c6eSApple OSS Distributions #define ENV_QOS_QUEUE_OVERRIDE  (1)
51*4d495c6eSApple OSS Distributions #define ENV_QOS_AFTER_OVERRIDE  (2)
52*4d495c6eSApple OSS Distributions 
53*4d495c6eSApple OSS Distributions #define USR_THROTTLE_LEVEL_TIER0 0
54*4d495c6eSApple OSS Distributions #define USR_THROTTLE_LEVEL_TIER1 1
55*4d495c6eSApple OSS Distributions 
56*4d495c6eSApple OSS Distributions struct test_msg {
57*4d495c6eSApple OSS Distributions 	mach_msg_header_t header;
58*4d495c6eSApple OSS Distributions 	mach_msg_body_t body;
59*4d495c6eSApple OSS Distributions 	mach_msg_port_descriptor_t port_descriptor;
60*4d495c6eSApple OSS Distributions 	mach_msg_option_t opts;
61*4d495c6eSApple OSS Distributions 	mach_msg_priority_t qos;
62*4d495c6eSApple OSS Distributions };
63*4d495c6eSApple OSS Distributions 
64*4d495c6eSApple OSS Distributions #pragma mark pthread callbacks
65*4d495c6eSApple OSS Distributions 
66*4d495c6eSApple OSS Distributions static pthread_t
67*4d495c6eSApple OSS Distributions thread_create_at_qos(qos_class_t qos, void * (*function)(void *));
68*4d495c6eSApple OSS Distributions static void
69*4d495c6eSApple OSS Distributions send(mach_port_t send_port, mach_port_t reply_port, mach_port_t msg_port, qos_class_t qos, mach_msg_option_t options);
70*4d495c6eSApple OSS Distributions static void
71*4d495c6eSApple OSS Distributions enable_kevent(uint64_t *workloop_id, unsigned long long port);
72*4d495c6eSApple OSS Distributions static void
73*4d495c6eSApple OSS Distributions populate_kevent(struct kevent_qos_s *kev, unsigned long long port);
74*4d495c6eSApple OSS Distributions 
75*4d495c6eSApple OSS Distributions static void
worker_cb(pthread_priority_t __unused priority)76*4d495c6eSApple OSS Distributions worker_cb(pthread_priority_t __unused priority)
77*4d495c6eSApple OSS Distributions {
78*4d495c6eSApple OSS Distributions 	T_FAIL("a worker thread was created");
79*4d495c6eSApple OSS Distributions }
80*4d495c6eSApple OSS Distributions 
81*4d495c6eSApple OSS Distributions static void
event_cb(void ** __unused events,int * __unused nevents)82*4d495c6eSApple OSS Distributions event_cb(void ** __unused events, int * __unused nevents)
83*4d495c6eSApple OSS Distributions {
84*4d495c6eSApple OSS Distributions 	T_FAIL("a kevent routine was called instead of workloop");
85*4d495c6eSApple OSS Distributions }
86*4d495c6eSApple OSS Distributions 
87*4d495c6eSApple OSS Distributions static uint32_t
get_user_promotion_basepri(void)88*4d495c6eSApple OSS Distributions get_user_promotion_basepri(void)
89*4d495c6eSApple OSS Distributions {
90*4d495c6eSApple OSS Distributions 	mach_msg_type_number_t count = THREAD_POLICY_STATE_COUNT;
91*4d495c6eSApple OSS Distributions 	struct thread_policy_state thread_policy;
92*4d495c6eSApple OSS Distributions 	boolean_t get_default = FALSE;
93*4d495c6eSApple OSS Distributions 	mach_port_t thread_port = pthread_mach_thread_np(pthread_self());
94*4d495c6eSApple OSS Distributions 
95*4d495c6eSApple OSS Distributions 	kern_return_t kr = thread_policy_get(thread_port, THREAD_POLICY_STATE,
96*4d495c6eSApple OSS Distributions 	    (thread_policy_t)&thread_policy, &count, &get_default);
97*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "thread_policy_get");
98*4d495c6eSApple OSS Distributions 	return thread_policy.thps_user_promotion_basepri;
99*4d495c6eSApple OSS Distributions }
100*4d495c6eSApple OSS Distributions 
101*4d495c6eSApple OSS Distributions static uint32_t
get_thread_iotier(void)102*4d495c6eSApple OSS Distributions get_thread_iotier(void)
103*4d495c6eSApple OSS Distributions {
104*4d495c6eSApple OSS Distributions 	mach_msg_type_number_t count = THREAD_POLICY_STATE_COUNT;
105*4d495c6eSApple OSS Distributions 	struct thread_policy_state thread_policy;
106*4d495c6eSApple OSS Distributions 	boolean_t get_default = FALSE;
107*4d495c6eSApple OSS Distributions 	mach_port_t thread_port = pthread_mach_thread_np(pthread_self());
108*4d495c6eSApple OSS Distributions 
109*4d495c6eSApple OSS Distributions 	kern_return_t kr = thread_policy_get(thread_port, THREAD_POLICY_STATE,
110*4d495c6eSApple OSS Distributions 	    (thread_policy_t)&thread_policy, &count, &get_default);
111*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "thread_policy_get");
112*4d495c6eSApple OSS Distributions 	return (thread_policy.effective >> POLICY_EFF_IO_TIER_SHIFT) & POLICY_EFF_IO_TIER_MASK;
113*4d495c6eSApple OSS Distributions }
114*4d495c6eSApple OSS Distributions 
115*4d495c6eSApple OSS Distributions #define EXPECT_QOS_EQ(qos, ...) do { \
116*4d495c6eSApple OSS Distributions 	        if ((qos) == QOS_CLASS_USER_INTERACTIVE) { \
117*4d495c6eSApple OSS Distributions 	                T_EXPECT_EFFECTIVE_QOS_EQ(QOS_CLASS_USER_INITIATED, __VA_ARGS__); \
118*4d495c6eSApple OSS Distributions 	                T_EXPECT_EQ(47u, get_user_promotion_basepri(), __VA_ARGS__); \
119*4d495c6eSApple OSS Distributions 	        } else { \
120*4d495c6eSApple OSS Distributions 	                T_EXPECT_EFFECTIVE_QOS_EQ(qos, __VA_ARGS__); \
121*4d495c6eSApple OSS Distributions 	        } \
122*4d495c6eSApple OSS Distributions 	} while (0)
123*4d495c6eSApple OSS Distributions 
124*4d495c6eSApple OSS Distributions #define EXPECT_TEST_MSG(_ke)  do { \
125*4d495c6eSApple OSS Distributions 	        struct kevent_qos_s *ke = _ke; \
126*4d495c6eSApple OSS Distributions 	        mach_msg_header_t *hdr = (mach_msg_header_t *)ke->ext[0]; \
127*4d495c6eSApple OSS Distributions 	        T_ASSERT_NOTNULL(hdr, "has a message"); \
128*4d495c6eSApple OSS Distributions 	        T_ASSERT_EQ(hdr->msgh_size, (uint32_t)sizeof(struct test_msg), "of the right size"); \
129*4d495c6eSApple OSS Distributions 	        struct test_msg *tmsg = (struct test_msg *)hdr; \
130*4d495c6eSApple OSS Distributions 	        if (tmsg->opts & MACH_SEND_PROPAGATE_QOS) { \
131*4d495c6eSApple OSS Distributions 	                T_EXPECT_EQ(tmsg->qos, ((uint32_t)(ke->ext[2] >> 32)), \
132*4d495c6eSApple OSS Distributions 	                                "propagation works"); \
133*4d495c6eSApple OSS Distributions 	        } \
134*4d495c6eSApple OSS Distributions 	} while (0)
135*4d495c6eSApple OSS Distributions 
136*4d495c6eSApple OSS Distributions /*
137*4d495c6eSApple OSS Distributions  * Basic WL handler callback, it sleeps for n seconds and then checks the
138*4d495c6eSApple OSS Distributions  * effective Qos of the servicer thread.
139*4d495c6eSApple OSS Distributions  */
140*4d495c6eSApple OSS Distributions static void
workloop_cb_test_intransit(uint64_t * workloop_id __unused,void ** eventslist,int * events)141*4d495c6eSApple OSS Distributions workloop_cb_test_intransit(uint64_t *workloop_id __unused, void **eventslist, int *events)
142*4d495c6eSApple OSS Distributions {
143*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_intransit called. "
144*4d495c6eSApple OSS Distributions 	    "Will wait for %d seconds to make sure client enqueues the sync msg \n",
145*4d495c6eSApple OSS Distributions 	    2 * RECV_TIMEOUT_SECS);
146*4d495c6eSApple OSS Distributions 
147*4d495c6eSApple OSS Distributions 	EXPECT_TEST_MSG(*eventslist);
148*4d495c6eSApple OSS Distributions 
149*4d495c6eSApple OSS Distributions 	/* Wait for the client to send the high priority message to override the qos */
150*4d495c6eSApple OSS Distributions 	sleep(2 * RECV_TIMEOUT_SECS);
151*4d495c6eSApple OSS Distributions 
152*4d495c6eSApple OSS Distributions 	/* Skip the test if we can't check Qos */
153*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
154*4d495c6eSApple OSS Distributions 
155*4d495c6eSApple OSS Distributions 	/* The effective Qos should be the one expected after override */
156*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
157*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
158*4d495c6eSApple OSS Distributions 
159*4d495c6eSApple OSS Distributions 	*events = 0;
160*4d495c6eSApple OSS Distributions 	T_END;
161*4d495c6eSApple OSS Distributions }
162*4d495c6eSApple OSS Distributions 
163*4d495c6eSApple OSS Distributions /*
164*4d495c6eSApple OSS Distributions  * WL handler which checks if the servicer thread has correct Qos.
165*4d495c6eSApple OSS Distributions  */
166*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send(uint64_t * workloop_id __unused,void ** eventslist,int * events)167*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send(uint64_t *workloop_id __unused, void **eventslist, int *events)
168*4d495c6eSApple OSS Distributions {
169*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send called");
170*4d495c6eSApple OSS Distributions 
171*4d495c6eSApple OSS Distributions 	EXPECT_TEST_MSG(*eventslist);
172*4d495c6eSApple OSS Distributions 
173*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
174*4d495c6eSApple OSS Distributions 
175*4d495c6eSApple OSS Distributions 	/* The effective Qos should be the one expected after override */
176*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
177*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
178*4d495c6eSApple OSS Distributions 
179*4d495c6eSApple OSS Distributions 	*events = 0;
180*4d495c6eSApple OSS Distributions 	T_END;
181*4d495c6eSApple OSS Distributions }
182*4d495c6eSApple OSS Distributions 
183*4d495c6eSApple OSS Distributions /*
184*4d495c6eSApple OSS Distributions  * WL handler which checks if the servicer thread has correct Qos.
185*4d495c6eSApple OSS Distributions  */
186*4d495c6eSApple OSS Distributions static void
workloop_cb_test_kernel_sync_send(uint64_t * workloop_id __unused,void ** eventslist,int * events)187*4d495c6eSApple OSS Distributions workloop_cb_test_kernel_sync_send(uint64_t *workloop_id __unused, void **eventslist, int *events)
188*4d495c6eSApple OSS Distributions {
189*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_kernel_sync_send called");
190*4d495c6eSApple OSS Distributions 
191*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
192*4d495c6eSApple OSS Distributions 
193*4d495c6eSApple OSS Distributions 	/* Wait for the kernel upcall to block on receive */
194*4d495c6eSApple OSS Distributions 	sleep(2 * RECV_TIMEOUT_SECS);
195*4d495c6eSApple OSS Distributions 
196*4d495c6eSApple OSS Distributions 	/* The effective Qos should be the one expected after override */
197*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
198*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
199*4d495c6eSApple OSS Distributions 
200*4d495c6eSApple OSS Distributions 	*events = 0;
201*4d495c6eSApple OSS Distributions 	T_END;
202*4d495c6eSApple OSS Distributions }
203*4d495c6eSApple OSS Distributions 
204*4d495c6eSApple OSS Distributions /*
205*4d495c6eSApple OSS Distributions  * WL handler which checks if the servicer thread has correct Qos.
206*4d495c6eSApple OSS Distributions  */
207*4d495c6eSApple OSS Distributions static void
workloop_cb_test_kernel_async_send(uint64_t * workloop_id __unused,void ** eventslist,int * events)208*4d495c6eSApple OSS Distributions workloop_cb_test_kernel_async_send(uint64_t *workloop_id __unused, void **eventslist, int *events)
209*4d495c6eSApple OSS Distributions {
210*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_kernel_sync_send called");
211*4d495c6eSApple OSS Distributions 
212*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
213*4d495c6eSApple OSS Distributions 
214*4d495c6eSApple OSS Distributions 	/* The effective Qos should be the one expected after override */
215*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
216*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
217*4d495c6eSApple OSS Distributions 
218*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(get_thread_iotier(), USR_THROTTLE_LEVEL_TIER0, "Thread IOTier has correct override");
219*4d495c6eSApple OSS Distributions 
220*4d495c6eSApple OSS Distributions 	*events = 0;
221*4d495c6eSApple OSS Distributions 	T_END;
222*4d495c6eSApple OSS Distributions }
223*4d495c6eSApple OSS Distributions 
224*4d495c6eSApple OSS Distributions /*
225*4d495c6eSApple OSS Distributions  * WL handler which checks the overridden Qos and then enables the knote and checks
226*4d495c6eSApple OSS Distributions  * for the Qos again if that dropped the sync ipc override.
227*4d495c6eSApple OSS Distributions  */
228*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_and_enable(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)229*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_and_enable(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
230*4d495c6eSApple OSS Distributions {
231*4d495c6eSApple OSS Distributions 	unsigned override_priority;
232*4d495c6eSApple OSS Distributions 	unsigned reenable_priority;
233*4d495c6eSApple OSS Distributions 
234*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_and_enable called");
235*4d495c6eSApple OSS Distributions 
236*4d495c6eSApple OSS Distributions 	EXPECT_TEST_MSG(*eventslist);
237*4d495c6eSApple OSS Distributions 
238*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
239*4d495c6eSApple OSS Distributions 
240*4d495c6eSApple OSS Distributions 	/* The effective Qos should be the one expected after override */
241*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
242*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
243*4d495c6eSApple OSS Distributions 
244*4d495c6eSApple OSS Distributions 	/* Snapshot the current override priority */
245*4d495c6eSApple OSS Distributions 	override_priority = get_user_promotion_basepri();
246*4d495c6eSApple OSS Distributions 
247*4d495c6eSApple OSS Distributions 	/* Enable the knote */
248*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
249*4d495c6eSApple OSS Distributions 	enable_kevent(workloop_id, kev->ident);
250*4d495c6eSApple OSS Distributions 
251*4d495c6eSApple OSS Distributions 	/*
252*4d495c6eSApple OSS Distributions 	 * Check if the override has been dropped, check for priority instead of qos since
253*4d495c6eSApple OSS Distributions 	 * there will be async qos push.
254*4d495c6eSApple OSS Distributions 	 */
255*4d495c6eSApple OSS Distributions 	reenable_priority = get_user_promotion_basepri();
256*4d495c6eSApple OSS Distributions 	T_EXPECT_LT(reenable_priority, override_priority,
257*4d495c6eSApple OSS Distributions 	    "thread's current override priority %d should be less than override priority prior to enabling knote %d",
258*4d495c6eSApple OSS Distributions 	    reenable_priority, override_priority);
259*4d495c6eSApple OSS Distributions 
260*4d495c6eSApple OSS Distributions 	*events = 0;
261*4d495c6eSApple OSS Distributions 	T_END;
262*4d495c6eSApple OSS Distributions }
263*4d495c6eSApple OSS Distributions 
264*4d495c6eSApple OSS Distributions /*
265*4d495c6eSApple OSS Distributions  * WL handler which checks the overridden Qos and then handoffs the IPC,
266*4d495c6eSApple OSS Distributions  * enables the knote and checks for the Qos again that it hasn't dropped the sync ipc override.
267*4d495c6eSApple OSS Distributions  */
268*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_and_enable_handoff(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)269*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_and_enable_handoff(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
270*4d495c6eSApple OSS Distributions {
271*4d495c6eSApple OSS Distributions 	unsigned override_priority;
272*4d495c6eSApple OSS Distributions 	int error;
273*4d495c6eSApple OSS Distributions 
274*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_and_enable_handoff called");
275*4d495c6eSApple OSS Distributions 
276*4d495c6eSApple OSS Distributions 	EXPECT_TEST_MSG(*eventslist);
277*4d495c6eSApple OSS Distributions 
278*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
279*4d495c6eSApple OSS Distributions 
280*4d495c6eSApple OSS Distributions 	/* The effective Qos should be the one expected after override */
281*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
282*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should be %s",
283*4d495c6eSApple OSS Distributions 	    g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
284*4d495c6eSApple OSS Distributions 
285*4d495c6eSApple OSS Distributions 	/* Snapshot the current override priority */
286*4d495c6eSApple OSS Distributions 	override_priority = get_user_promotion_basepri();
287*4d495c6eSApple OSS Distributions 
288*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
289*4d495c6eSApple OSS Distributions 	mach_msg_header_t *hdr = (mach_msg_header_t *)kev->ext[0];
290*4d495c6eSApple OSS Distributions 
291*4d495c6eSApple OSS Distributions 	/* handoff the IPC */
292*4d495c6eSApple OSS Distributions 	struct kevent_qos_s handoff_kev = {
293*4d495c6eSApple OSS Distributions 		.filter = EVFILT_WORKLOOP,
294*4d495c6eSApple OSS Distributions 		.ident = hdr->msgh_remote_port,
295*4d495c6eSApple OSS Distributions 		.flags = EV_ADD | EV_DISABLE,
296*4d495c6eSApple OSS Distributions 		.fflags = 0x80000000,
297*4d495c6eSApple OSS Distributions 	};
298*4d495c6eSApple OSS Distributions 
299*4d495c6eSApple OSS Distributions 	error = kevent_id(*workloop_id, &handoff_kev, 1, &handoff_kev, 1, NULL,
300*4d495c6eSApple OSS Distributions 	    NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_ERROR_EVENTS | KEVENT_FLAG_DYNAMIC_KQ_MUST_EXIST);
301*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(error, "kevent_id");
302*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(0, error, "Handed off the sync IPC");
303*4d495c6eSApple OSS Distributions 
304*4d495c6eSApple OSS Distributions 	/* Enable the knote */
305*4d495c6eSApple OSS Distributions 	enable_kevent(workloop_id, kev->ident);
306*4d495c6eSApple OSS Distributions 
307*4d495c6eSApple OSS Distributions 	/*
308*4d495c6eSApple OSS Distributions 	 * Check if the override has not been dropped.
309*4d495c6eSApple OSS Distributions 	 */
310*4d495c6eSApple OSS Distributions 	EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
311*4d495c6eSApple OSS Distributions 	    "dispatch_source event handler QoS should still be %s",
312*4d495c6eSApple OSS Distributions 	    g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
313*4d495c6eSApple OSS Distributions 
314*4d495c6eSApple OSS Distributions 	*events = 0;
315*4d495c6eSApple OSS Distributions 	T_END;
316*4d495c6eSApple OSS Distributions }
317*4d495c6eSApple OSS Distributions 
318*4d495c6eSApple OSS Distributions /*
319*4d495c6eSApple OSS Distributions  * WL handler receives the first message and checks sync ipc override, then enables the knote
320*4d495c6eSApple OSS Distributions  * and receives 2nd message and checks it sync ipc override.
321*4d495c6eSApple OSS Distributions  */
322*4d495c6eSApple OSS Distributions static int send_two_sync_handler_called = 0;
323*4d495c6eSApple OSS Distributions static void
workloop_cb_test_send_two_sync(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)324*4d495c6eSApple OSS Distributions workloop_cb_test_send_two_sync(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
325*4d495c6eSApple OSS Distributions {
326*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_send_two_sync called for %d time", send_two_sync_handler_called + 1);
327*4d495c6eSApple OSS Distributions 
328*4d495c6eSApple OSS Distributions 	EXPECT_TEST_MSG(*eventslist);
329*4d495c6eSApple OSS Distributions 
330*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
331*4d495c6eSApple OSS Distributions 
332*4d495c6eSApple OSS Distributions 	T_LOG("Number of events received is %d\n", *events);
333*4d495c6eSApple OSS Distributions 
334*4d495c6eSApple OSS Distributions 	if (send_two_sync_handler_called == 0) {
335*4d495c6eSApple OSS Distributions 		/* The effective Qos should be the one expected after override */
336*4d495c6eSApple OSS Distributions 		EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
337*4d495c6eSApple OSS Distributions 		    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
338*4d495c6eSApple OSS Distributions 
339*4d495c6eSApple OSS Distributions 		/* Enable the knote to get 2nd message */
340*4d495c6eSApple OSS Distributions 		struct kevent_qos_s *kev = *eventslist;
341*4d495c6eSApple OSS Distributions 		uint64_t port = kev->ident;
342*4d495c6eSApple OSS Distributions 		populate_kevent(kev, port);
343*4d495c6eSApple OSS Distributions 		*events = 1;
344*4d495c6eSApple OSS Distributions 	} else {
345*4d495c6eSApple OSS Distributions 		EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_BEFORE_OVERRIDE],
346*4d495c6eSApple OSS Distributions 		    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_BEFORE_OVERRIDE]);
347*4d495c6eSApple OSS Distributions 		*events = 0;
348*4d495c6eSApple OSS Distributions 		T_END;
349*4d495c6eSApple OSS Distributions 	}
350*4d495c6eSApple OSS Distributions 	send_two_sync_handler_called++;
351*4d495c6eSApple OSS Distributions }
352*4d495c6eSApple OSS Distributions 
353*4d495c6eSApple OSS Distributions /*
354*4d495c6eSApple OSS Distributions  * Checks the sync ipc override and then waits for client to destroy the
355*4d495c6eSApple OSS Distributions  * special reply port and checks if that removes the sync ipc override.
356*4d495c6eSApple OSS Distributions  */
357*4d495c6eSApple OSS Distributions static boolean_t two_send_and_destroy_test_passed = FALSE;
358*4d495c6eSApple OSS Distributions static int two_send_and_destroy_handler = 0;
359*4d495c6eSApple OSS Distributions static void
workloop_cb_test_two_send_and_destroy(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist __unused,int * events)360*4d495c6eSApple OSS Distributions workloop_cb_test_two_send_and_destroy(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist __unused, int *events)
361*4d495c6eSApple OSS Distributions {
362*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_two_send_and_destroy called %d times", two_send_and_destroy_handler + 1);
363*4d495c6eSApple OSS Distributions 
364*4d495c6eSApple OSS Distributions 	EXPECT_TEST_MSG(*eventslist);
365*4d495c6eSApple OSS Distributions 
366*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
367*4d495c6eSApple OSS Distributions 
368*4d495c6eSApple OSS Distributions 	if (two_send_and_destroy_handler == 0) {
369*4d495c6eSApple OSS Distributions 		/* Sleep to make sure the mqueue gets full */
370*4d495c6eSApple OSS Distributions 		sleep(RECV_TIMEOUT_SECS);
371*4d495c6eSApple OSS Distributions 
372*4d495c6eSApple OSS Distributions 		/* The effective Qos should be the one expected after override */
373*4d495c6eSApple OSS Distributions 		EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
374*4d495c6eSApple OSS Distributions 		    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
375*4d495c6eSApple OSS Distributions 
376*4d495c6eSApple OSS Distributions 		sleep(SEND_TIMEOUT_SECS);
377*4d495c6eSApple OSS Distributions 
378*4d495c6eSApple OSS Distributions 		/* Special reply port should have been destroyed, check Qos again */
379*4d495c6eSApple OSS Distributions 		EXPECT_QOS_EQ(g_expected_qos[ENV_QOS_BEFORE_OVERRIDE],
380*4d495c6eSApple OSS Distributions 		    "dispatch_source event handler QoS should be %s", g_expected_qos_name[ENV_QOS_BEFORE_OVERRIDE]);
381*4d495c6eSApple OSS Distributions 
382*4d495c6eSApple OSS Distributions 		two_send_and_destroy_test_passed = TRUE;
383*4d495c6eSApple OSS Distributions 	} else {
384*4d495c6eSApple OSS Distributions 		if (two_send_and_destroy_test_passed) {
385*4d495c6eSApple OSS Distributions 			T_END;
386*4d495c6eSApple OSS Distributions 		}
387*4d495c6eSApple OSS Distributions 	}
388*4d495c6eSApple OSS Distributions 
389*4d495c6eSApple OSS Distributions 	/* Enable the knote to get next message */
390*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
391*4d495c6eSApple OSS Distributions 	uint64_t port = kev->ident;
392*4d495c6eSApple OSS Distributions 	populate_kevent(kev, port);
393*4d495c6eSApple OSS Distributions 	*events = 1;
394*4d495c6eSApple OSS Distributions 	two_send_and_destroy_handler++;
395*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
396*4d495c6eSApple OSS Distributions }
397*4d495c6eSApple OSS Distributions 
398*4d495c6eSApple OSS Distributions static mach_port_type_t
get_reply_port(struct kevent_qos_s * kev)399*4d495c6eSApple OSS Distributions get_reply_port(struct kevent_qos_s *kev)
400*4d495c6eSApple OSS Distributions {
401*4d495c6eSApple OSS Distributions 	mach_msg_header_t *hdr;
402*4d495c6eSApple OSS Distributions 	mach_port_t reply_port;
403*4d495c6eSApple OSS Distributions 	mach_port_type_t type;
404*4d495c6eSApple OSS Distributions 	kern_return_t kr;
405*4d495c6eSApple OSS Distributions 
406*4d495c6eSApple OSS Distributions 	hdr = (void*)kev->ext[0];
407*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(hdr, "msg hdr");
408*4d495c6eSApple OSS Distributions 
409*4d495c6eSApple OSS Distributions 	reply_port = hdr->msgh_remote_port;
410*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(reply_port), "reply port valid");
411*4d495c6eSApple OSS Distributions 	kr = mach_port_type(mach_task_self(), reply_port, &type);
412*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_type");
413*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(type & MACH_PORT_TYPE_SEND_ONCE, "send once received");
414*4d495c6eSApple OSS Distributions 
415*4d495c6eSApple OSS Distributions 	return reply_port;
416*4d495c6eSApple OSS Distributions }
417*4d495c6eSApple OSS Distributions 
418*4d495c6eSApple OSS Distributions static void
send_reply(mach_port_t reply_port)419*4d495c6eSApple OSS Distributions send_reply(mach_port_t reply_port)
420*4d495c6eSApple OSS Distributions {
421*4d495c6eSApple OSS Distributions 	kern_return_t kr;
422*4d495c6eSApple OSS Distributions 
423*4d495c6eSApple OSS Distributions 	struct {
424*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
425*4d495c6eSApple OSS Distributions 	} send_msg = {
426*4d495c6eSApple OSS Distributions 		.header = {
427*4d495c6eSApple OSS Distributions 			.msgh_remote_port = reply_port,
428*4d495c6eSApple OSS Distributions 			.msgh_local_port  = MACH_PORT_NULL,
429*4d495c6eSApple OSS Distributions 			.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0),
430*4d495c6eSApple OSS Distributions 			.msgh_id          = 0x100,
431*4d495c6eSApple OSS Distributions 			.msgh_size        = sizeof(send_msg),
432*4d495c6eSApple OSS Distributions 		},
433*4d495c6eSApple OSS Distributions 	};
434*4d495c6eSApple OSS Distributions 
435*4d495c6eSApple OSS Distributions 	kr = mach_msg(&(send_msg.header),
436*4d495c6eSApple OSS Distributions 	    MACH_SEND_MSG,
437*4d495c6eSApple OSS Distributions 	    send_msg.header.msgh_size,
438*4d495c6eSApple OSS Distributions 	    0,
439*4d495c6eSApple OSS Distributions 	    MACH_PORT_NULL,
440*4d495c6eSApple OSS Distributions 	    0,
441*4d495c6eSApple OSS Distributions 	    0);
442*4d495c6eSApple OSS Distributions 
443*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "server mach_msg");
444*4d495c6eSApple OSS Distributions }
445*4d495c6eSApple OSS Distributions 
446*4d495c6eSApple OSS Distributions static void
populate_kevent(struct kevent_qos_s * kev,unsigned long long port)447*4d495c6eSApple OSS Distributions populate_kevent(struct kevent_qos_s *kev, unsigned long long port)
448*4d495c6eSApple OSS Distributions {
449*4d495c6eSApple OSS Distributions 	memset(kev, 0, sizeof(struct kevent_qos_s));
450*4d495c6eSApple OSS Distributions 	kev->ident = port;
451*4d495c6eSApple OSS Distributions 	kev->filter = EVFILT_MACHPORT;
452*4d495c6eSApple OSS Distributions 	kev->flags = EV_ADD | EV_ENABLE | EV_UDATA_SPECIFIC | EV_DISPATCH | EV_VANISHED;
453*4d495c6eSApple OSS Distributions 	kev->fflags = (MACH_RCV_MSG | MACH_RCV_VOUCHER | MACH_RCV_LARGE | MACH_RCV_LARGE_IDENTITY |
454*4d495c6eSApple OSS Distributions 	    MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV) |
455*4d495c6eSApple OSS Distributions 	    MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
456*4d495c6eSApple OSS Distributions 	kev->data = 1;
457*4d495c6eSApple OSS Distributions }
458*4d495c6eSApple OSS Distributions 
459*4d495c6eSApple OSS Distributions static void
enable_kevent(uint64_t * workloop_id,unsigned long long port)460*4d495c6eSApple OSS Distributions enable_kevent(uint64_t *workloop_id, unsigned long long port)
461*4d495c6eSApple OSS Distributions {
462*4d495c6eSApple OSS Distributions 	struct kevent_qos_s kev;
463*4d495c6eSApple OSS Distributions 	int error;
464*4d495c6eSApple OSS Distributions 
465*4d495c6eSApple OSS Distributions 	populate_kevent(&kev, port);
466*4d495c6eSApple OSS Distributions 	struct kevent_qos_s kev_err[] = {{ 0 }};
467*4d495c6eSApple OSS Distributions 
468*4d495c6eSApple OSS Distributions 	error = kevent_id(*workloop_id, &kev, 1, kev_err, 1, NULL,
469*4d495c6eSApple OSS Distributions 	    NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_ERROR_EVENTS | KEVENT_FLAG_DYNAMIC_KQ_MUST_EXIST);
470*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(error, "kevent_id");
471*4d495c6eSApple OSS Distributions }
472*4d495c6eSApple OSS Distributions 
473*4d495c6eSApple OSS Distributions /*
474*4d495c6eSApple OSS Distributions  * WL handler which sends a msg to the client from handler.
475*4d495c6eSApple OSS Distributions  */
476*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_reply(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)477*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_reply(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
478*4d495c6eSApple OSS Distributions {
479*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_reply called");
480*4d495c6eSApple OSS Distributions 
481*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
482*4d495c6eSApple OSS Distributions 
483*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
484*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
485*4d495c6eSApple OSS Distributions 
486*4d495c6eSApple OSS Distributions 	/* send reply */
487*4d495c6eSApple OSS Distributions 	send_reply(get_reply_port(*eventslist));
488*4d495c6eSApple OSS Distributions 
489*4d495c6eSApple OSS Distributions 	*events = 0;
490*4d495c6eSApple OSS Distributions }
491*4d495c6eSApple OSS Distributions 
492*4d495c6eSApple OSS Distributions /*
493*4d495c6eSApple OSS Distributions  * WL handler which deallocates reply port.
494*4d495c6eSApple OSS Distributions  */
495*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_deallocate(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)496*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_deallocate(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
497*4d495c6eSApple OSS Distributions {
498*4d495c6eSApple OSS Distributions 	mach_port_t reply_port;
499*4d495c6eSApple OSS Distributions 	kern_return_t kr;
500*4d495c6eSApple OSS Distributions 
501*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_deallocate called");
502*4d495c6eSApple OSS Distributions 
503*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
504*4d495c6eSApple OSS Distributions 
505*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
506*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
507*4d495c6eSApple OSS Distributions 
508*4d495c6eSApple OSS Distributions 	reply_port = get_reply_port(*eventslist);
509*4d495c6eSApple OSS Distributions 
510*4d495c6eSApple OSS Distributions 	/* deallocate port */
511*4d495c6eSApple OSS Distributions 	kr = mach_port_deallocate(mach_task_self(), reply_port);
512*4d495c6eSApple OSS Distributions 
513*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_deallocate");
514*4d495c6eSApple OSS Distributions 
515*4d495c6eSApple OSS Distributions 	*events = 0;
516*4d495c6eSApple OSS Distributions 
517*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
518*4d495c6eSApple OSS Distributions }
519*4d495c6eSApple OSS Distributions 
520*4d495c6eSApple OSS Distributions 
521*4d495c6eSApple OSS Distributions /*
522*4d495c6eSApple OSS Distributions  * WL handler which sends a msg to the client before enabling the event from handler.
523*4d495c6eSApple OSS Distributions  */
524*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_reply_kevent(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)525*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_reply_kevent(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
526*4d495c6eSApple OSS Distributions {
527*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_reply_kevent called");
528*4d495c6eSApple OSS Distributions 
529*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
530*4d495c6eSApple OSS Distributions 
531*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
532*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(((*eventslist)->filter), EVFILT_MACHPORT, "received EVFILT_MACHPORT");
533*4d495c6eSApple OSS Distributions 
534*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
535*4d495c6eSApple OSS Distributions 
536*4d495c6eSApple OSS Distributions 	/* send reply */
537*4d495c6eSApple OSS Distributions 	send_reply(get_reply_port(kev));
538*4d495c6eSApple OSS Distributions 
539*4d495c6eSApple OSS Distributions 	/* Enable the knote */
540*4d495c6eSApple OSS Distributions 	enable_kevent(workloop_id, kev->ident);
541*4d495c6eSApple OSS Distributions 
542*4d495c6eSApple OSS Distributions 	*events = 0;
543*4d495c6eSApple OSS Distributions 
544*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
545*4d495c6eSApple OSS Distributions }
546*4d495c6eSApple OSS Distributions 
547*4d495c6eSApple OSS Distributions /*
548*4d495c6eSApple OSS Distributions  * WL handler which sends a msg to the client before enabling the event from pthread.
549*4d495c6eSApple OSS Distributions  */
550*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_reply_kevent_pthread(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)551*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_reply_kevent_pthread(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
552*4d495c6eSApple OSS Distributions {
553*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_reply_kevent_pthread called");
554*4d495c6eSApple OSS Distributions 
555*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
556*4d495c6eSApple OSS Distributions 
557*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
558*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
559*4d495c6eSApple OSS Distributions 
560*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
561*4d495c6eSApple OSS Distributions 
562*4d495c6eSApple OSS Distributions 	/* send reply */
563*4d495c6eSApple OSS Distributions 	send_reply(get_reply_port(kev));
564*4d495c6eSApple OSS Distributions 
565*4d495c6eSApple OSS Distributions 	populate_kevent(kev, kev->ident);
566*4d495c6eSApple OSS Distributions 
567*4d495c6eSApple OSS Distributions 	*events = 1;
568*4d495c6eSApple OSS Distributions 
569*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
570*4d495c6eSApple OSS Distributions }
571*4d495c6eSApple OSS Distributions 
572*4d495c6eSApple OSS Distributions /*
573*4d495c6eSApple OSS Distributions  * WL handler which sends a msg to the client after reenabling the event.
574*4d495c6eSApple OSS Distributions  */
575*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_kevent_reply(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)576*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_kevent_reply(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
577*4d495c6eSApple OSS Distributions {
578*4d495c6eSApple OSS Distributions 	T_LOG("workloop handler workloop_cb_test_sync_send_kevent_reply called");
579*4d495c6eSApple OSS Distributions 
580*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
581*4d495c6eSApple OSS Distributions 
582*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
583*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
584*4d495c6eSApple OSS Distributions 
585*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
586*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = get_reply_port(*eventslist);
587*4d495c6eSApple OSS Distributions 
588*4d495c6eSApple OSS Distributions 	/* Enable the knote */
589*4d495c6eSApple OSS Distributions 	enable_kevent(workloop_id, kev->ident);
590*4d495c6eSApple OSS Distributions 
591*4d495c6eSApple OSS Distributions 	/* send reply */
592*4d495c6eSApple OSS Distributions 	send_reply(reply_port);
593*4d495c6eSApple OSS Distributions 
594*4d495c6eSApple OSS Distributions 	*events = 0;
595*4d495c6eSApple OSS Distributions 
596*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
597*4d495c6eSApple OSS Distributions }
598*4d495c6eSApple OSS Distributions 
599*4d495c6eSApple OSS Distributions /*
600*4d495c6eSApple OSS Distributions  * WL handler that does nothing.
601*4d495c6eSApple OSS Distributions  */
602*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_do_nothing(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)603*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_do_nothing(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
604*4d495c6eSApple OSS Distributions {
605*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_do_nothing called");
606*4d495c6eSApple OSS Distributions 
607*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
608*4d495c6eSApple OSS Distributions 
609*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
610*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
611*4d495c6eSApple OSS Distributions 
612*4d495c6eSApple OSS Distributions 	/* do nothing */
613*4d495c6eSApple OSS Distributions 
614*4d495c6eSApple OSS Distributions 	*events = 0;
615*4d495c6eSApple OSS Distributions 
616*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
617*4d495c6eSApple OSS Distributions }
618*4d495c6eSApple OSS Distributions 
619*4d495c6eSApple OSS Distributions /*
620*4d495c6eSApple OSS Distributions  * WL handler that returns the event to reenable.
621*4d495c6eSApple OSS Distributions  */
622*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_do_nothing_kevent_pthread(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)623*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_do_nothing_kevent_pthread(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
624*4d495c6eSApple OSS Distributions {
625*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_do_nothing_kevent_pthread called");
626*4d495c6eSApple OSS Distributions 
627*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
628*4d495c6eSApple OSS Distributions 
629*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
630*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
631*4d495c6eSApple OSS Distributions 
632*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
633*4d495c6eSApple OSS Distributions 	populate_kevent(kev, kev->ident);
634*4d495c6eSApple OSS Distributions 
635*4d495c6eSApple OSS Distributions 	*events = 1;
636*4d495c6eSApple OSS Distributions 
637*4d495c6eSApple OSS Distributions 	T_LOG("handler returning \n");
638*4d495c6eSApple OSS Distributions }
639*4d495c6eSApple OSS Distributions 
640*4d495c6eSApple OSS Distributions /*
641*4d495c6eSApple OSS Distributions  * WL handler that exits.
642*4d495c6eSApple OSS Distributions  */
643*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_do_nothing_exit(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,__unused int * events)644*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_do_nothing_exit(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, __unused int *events)
645*4d495c6eSApple OSS Distributions {
646*4d495c6eSApple OSS Distributions 	T_LOG("workloop handler workloop_cb_test_sync_send_do_nothing_exit called");
647*4d495c6eSApple OSS Distributions 
648*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
649*4d495c6eSApple OSS Distributions 
650*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
651*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
652*4d495c6eSApple OSS Distributions 
653*4d495c6eSApple OSS Distributions 	/* call exit */
654*4d495c6eSApple OSS Distributions 	exit(0);
655*4d495c6eSApple OSS Distributions }
656*4d495c6eSApple OSS Distributions 
657*4d495c6eSApple OSS Distributions /*
658*4d495c6eSApple OSS Distributions  * WL handler which:
659*4d495c6eSApple OSS Distributions  * first sync sends a msg to the client and reenables kevent after
660*4d495c6eSApple OSS Distributions  * second sync sends a msg and reenables kevent after.
661*4d495c6eSApple OSS Distributions  */
662*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_reply_kevent_reply_kevent(uint64_t * workloop_id __unused,struct kevent_qos_s ** eventslist,int * events)663*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_reply_kevent_reply_kevent(uint64_t *workloop_id __unused, struct kevent_qos_s **eventslist, int *events)
664*4d495c6eSApple OSS Distributions {
665*4d495c6eSApple OSS Distributions 	T_LOG("Workloop handler workloop_cb_test_sync_send_reply_kevent_reply_kevent called");
666*4d495c6eSApple OSS Distributions 
667*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
668*4d495c6eSApple OSS Distributions 
669*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
670*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
671*4d495c6eSApple OSS Distributions 
672*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
673*4d495c6eSApple OSS Distributions 
674*4d495c6eSApple OSS Distributions 	/* send reply */
675*4d495c6eSApple OSS Distributions 	send_reply(get_reply_port(kev));
676*4d495c6eSApple OSS Distributions 
677*4d495c6eSApple OSS Distributions 	populate_kevent(kev, kev->ident);
678*4d495c6eSApple OSS Distributions 
679*4d495c6eSApple OSS Distributions 	*events = 1;
680*4d495c6eSApple OSS Distributions 
681*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
682*4d495c6eSApple OSS Distributions }
683*4d495c6eSApple OSS Distributions 
684*4d495c6eSApple OSS Distributions /*
685*4d495c6eSApple OSS Distributions  * WL handler which:
686*4d495c6eSApple OSS Distributions  * first sync reenables kevent and after sends a msg
687*4d495c6eSApple OSS Distributions  * second sync sends a msg and reenables kevent after.
688*4d495c6eSApple OSS Distributions  */
689*4d495c6eSApple OSS Distributions static int workloop_cb_test_sync_send_kevent_reply_reply_kevent_handler_called = 0;
690*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_kevent_reply_reply_kevent(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)691*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_kevent_reply_reply_kevent(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
692*4d495c6eSApple OSS Distributions {
693*4d495c6eSApple OSS Distributions 	T_LOG("workloop handler workloop_cb_test_sync_send_kevent_reply_reply_kevent called");
694*4d495c6eSApple OSS Distributions 
695*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
696*4d495c6eSApple OSS Distributions 
697*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
698*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
699*4d495c6eSApple OSS Distributions 
700*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
701*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = get_reply_port(kev);
702*4d495c6eSApple OSS Distributions 
703*4d495c6eSApple OSS Distributions 	if (workloop_cb_test_sync_send_kevent_reply_reply_kevent_handler_called == 0) {
704*4d495c6eSApple OSS Distributions 		workloop_cb_test_sync_send_kevent_reply_reply_kevent_handler_called = 1;
705*4d495c6eSApple OSS Distributions 
706*4d495c6eSApple OSS Distributions 		/* Enable the knote */
707*4d495c6eSApple OSS Distributions 		enable_kevent(workloop_id, kev->ident);
708*4d495c6eSApple OSS Distributions 
709*4d495c6eSApple OSS Distributions 		/* send reply */
710*4d495c6eSApple OSS Distributions 		send_reply(reply_port);
711*4d495c6eSApple OSS Distributions 
712*4d495c6eSApple OSS Distributions 		*events = 0;
713*4d495c6eSApple OSS Distributions 	} else {
714*4d495c6eSApple OSS Distributions 		/* send reply */
715*4d495c6eSApple OSS Distributions 		send_reply(reply_port);
716*4d495c6eSApple OSS Distributions 
717*4d495c6eSApple OSS Distributions 		/* Enable the knote */
718*4d495c6eSApple OSS Distributions 		enable_kevent(workloop_id, kev->ident);
719*4d495c6eSApple OSS Distributions 
720*4d495c6eSApple OSS Distributions 		*events = 0;
721*4d495c6eSApple OSS Distributions 	}
722*4d495c6eSApple OSS Distributions 
723*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
724*4d495c6eSApple OSS Distributions }
725*4d495c6eSApple OSS Distributions 
726*4d495c6eSApple OSS Distributions /*
727*4d495c6eSApple OSS Distributions  * WL handler which:
728*4d495c6eSApple OSS Distributions  * first sync reenables kevent and after sends a msg
729*4d495c6eSApple OSS Distributions  * second sync reenables kevent and after sends a msg
730*4d495c6eSApple OSS Distributions  */
731*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_kevent_reply_kevent_reply(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)732*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_kevent_reply_kevent_reply(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
733*4d495c6eSApple OSS Distributions {
734*4d495c6eSApple OSS Distributions 	T_LOG("workloop handler workloop_cb_test_sync_send_kevent_reply_kevent_reply called");
735*4d495c6eSApple OSS Distributions 
736*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
737*4d495c6eSApple OSS Distributions 
738*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
739*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
740*4d495c6eSApple OSS Distributions 
741*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
742*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = get_reply_port(kev);
743*4d495c6eSApple OSS Distributions 
744*4d495c6eSApple OSS Distributions 	/* Enable the knote */
745*4d495c6eSApple OSS Distributions 	enable_kevent(workloop_id, kev->ident);
746*4d495c6eSApple OSS Distributions 
747*4d495c6eSApple OSS Distributions 	/* send reply */
748*4d495c6eSApple OSS Distributions 	send_reply(reply_port);
749*4d495c6eSApple OSS Distributions 
750*4d495c6eSApple OSS Distributions 	*events = 0;
751*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
752*4d495c6eSApple OSS Distributions }
753*4d495c6eSApple OSS Distributions 
754*4d495c6eSApple OSS Distributions /*
755*4d495c6eSApple OSS Distributions  * WL handler which:
756*4d495c6eSApple OSS Distributions  * first sync ends a msg and reenables kevent after
757*4d495c6eSApple OSS Distributions  * second sync reenables kevent and sends a msg after
758*4d495c6eSApple OSS Distributions  */
759*4d495c6eSApple OSS Distributions static int workloop_cb_test_sync_send_reply_kevent_kevent_reply_handler_called = 0;
760*4d495c6eSApple OSS Distributions static void
workloop_cb_test_sync_send_reply_kevent_kevent_reply(uint64_t * workloop_id,struct kevent_qos_s ** eventslist,int * events)761*4d495c6eSApple OSS Distributions workloop_cb_test_sync_send_reply_kevent_kevent_reply(uint64_t *workloop_id, struct kevent_qos_s **eventslist, int *events)
762*4d495c6eSApple OSS Distributions {
763*4d495c6eSApple OSS Distributions 	T_LOG("workloop handler workloop_cb_test_sync_send_reply_kevent_kevent_reply called");
764*4d495c6eSApple OSS Distributions 
765*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(geteuid(), 0, "kevent_qos test requires root privileges to run.");
766*4d495c6eSApple OSS Distributions 
767*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT(*events, 1, "events received");
768*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ_INT((*eventslist)->filter, EVFILT_MACHPORT, "received EVFILT_MACHPORT");
769*4d495c6eSApple OSS Distributions 
770*4d495c6eSApple OSS Distributions 	struct kevent_qos_s *kev = *eventslist;
771*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = get_reply_port(kev);
772*4d495c6eSApple OSS Distributions 
773*4d495c6eSApple OSS Distributions 	if (workloop_cb_test_sync_send_reply_kevent_kevent_reply_handler_called == 0) {
774*4d495c6eSApple OSS Distributions 		workloop_cb_test_sync_send_reply_kevent_kevent_reply_handler_called = 1;
775*4d495c6eSApple OSS Distributions 
776*4d495c6eSApple OSS Distributions 		/* send reply */
777*4d495c6eSApple OSS Distributions 		send_reply(reply_port);
778*4d495c6eSApple OSS Distributions 
779*4d495c6eSApple OSS Distributions 		populate_kevent(kev, kev->ident);
780*4d495c6eSApple OSS Distributions 
781*4d495c6eSApple OSS Distributions 		*events = 1;
782*4d495c6eSApple OSS Distributions 	} else {
783*4d495c6eSApple OSS Distributions 		/* Enable the knote */
784*4d495c6eSApple OSS Distributions 		enable_kevent(workloop_id, kev->ident);
785*4d495c6eSApple OSS Distributions 		/* send reply */
786*4d495c6eSApple OSS Distributions 		send_reply(reply_port);
787*4d495c6eSApple OSS Distributions 
788*4d495c6eSApple OSS Distributions 		*events = 0;
789*4d495c6eSApple OSS Distributions 	}
790*4d495c6eSApple OSS Distributions 
791*4d495c6eSApple OSS Distributions 	T_LOG("Handler returning \n");
792*4d495c6eSApple OSS Distributions }
793*4d495c6eSApple OSS Distributions #pragma mark Mach receive
794*4d495c6eSApple OSS Distributions 
795*4d495c6eSApple OSS Distributions #define KEVENT_QOS_SERVICE_NAME "com.apple.xnu.test.kevent_qos"
796*4d495c6eSApple OSS Distributions 
797*4d495c6eSApple OSS Distributions static mach_port_t
get_server_port(void)798*4d495c6eSApple OSS Distributions get_server_port(void)
799*4d495c6eSApple OSS Distributions {
800*4d495c6eSApple OSS Distributions 	mach_port_t port;
801*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_check_in(bootstrap_port,
802*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &port);
803*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "server bootstrap_check_in");
804*4d495c6eSApple OSS Distributions 	return port;
805*4d495c6eSApple OSS Distributions }
806*4d495c6eSApple OSS Distributions 
807*4d495c6eSApple OSS Distributions static void
env_set_qos(char ** env,qos_class_t qos[],const char * qos_name[],const char * wl_function)808*4d495c6eSApple OSS Distributions env_set_qos(char **env, qos_class_t qos[], const char *qos_name[], const char *wl_function)
809*4d495c6eSApple OSS Distributions {
810*4d495c6eSApple OSS Distributions 	int i;
811*4d495c6eSApple OSS Distributions 	char *qos_str, *qos_name_str;
812*4d495c6eSApple OSS Distributions 	for (i = 0; i < ENV_VAR_QOS; i++) {
813*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(asprintf(&qos_str, "%s=%d", qos_env[i], qos[i]),
814*4d495c6eSApple OSS Distributions 		    NULL);
815*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(
816*4d495c6eSApple OSS Distributions 			asprintf(&qos_name_str, "%s=%s", qos_name_env[i], qos_name[i]), NULL);
817*4d495c6eSApple OSS Distributions 		env[2 * i] = qos_str;
818*4d495c6eSApple OSS Distributions 		env[2 * i + 1] = qos_name_str;
819*4d495c6eSApple OSS Distributions 	}
820*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(asprintf(&env[2 * i], "%s=%s", wl_function_name, wl_function),
821*4d495c6eSApple OSS Distributions 	    NULL);
822*4d495c6eSApple OSS Distributions 	env[2 * i + 1] = NULL;
823*4d495c6eSApple OSS Distributions }
824*4d495c6eSApple OSS Distributions 
825*4d495c6eSApple OSS Distributions static void
environ_get_qos(qos_class_t qos[],const char * qos_name[],const char ** wl_function)826*4d495c6eSApple OSS Distributions environ_get_qos(qos_class_t qos[], const char *qos_name[], const char **wl_function)
827*4d495c6eSApple OSS Distributions {
828*4d495c6eSApple OSS Distributions 	char *qos_str;
829*4d495c6eSApple OSS Distributions 	char *qos_end;
830*4d495c6eSApple OSS Distributions 	int i;
831*4d495c6eSApple OSS Distributions 
832*4d495c6eSApple OSS Distributions 	for (i = 0; i < ENV_VAR_QOS; i++) {
833*4d495c6eSApple OSS Distributions 		qos_str = getenv(qos_env[i]);
834*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_NOTNULL(qos_str, "getenv(%s)", qos_env[i]);
835*4d495c6eSApple OSS Distributions 
836*4d495c6eSApple OSS Distributions 		unsigned long qos_l = strtoul(qos_str, &qos_end, 10);
837*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_EQ(*qos_end, '\0', "getenv(%s) = '%s' should be an "
838*4d495c6eSApple OSS Distributions 		    "integer", qos_env[i], qos_str);
839*4d495c6eSApple OSS Distributions 
840*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_LT(qos_l, (unsigned long)100, "getenv(%s) = '%s' should "
841*4d495c6eSApple OSS Distributions 		    "be less than 100", qos_env[i], qos_str);
842*4d495c6eSApple OSS Distributions 
843*4d495c6eSApple OSS Distributions 		qos[i] = (qos_class_t)qos_l;
844*4d495c6eSApple OSS Distributions 		qos_name[i] = getenv(qos_name_env[i]);
845*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_NOTNULL(qos_name[i], "getenv(%s)", qos_name_env[i]);
846*4d495c6eSApple OSS Distributions 	}
847*4d495c6eSApple OSS Distributions 	*wl_function = getenv(wl_function_name);
848*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(*wl_function, "getenv(%s)", wl_function_name);
849*4d495c6eSApple OSS Distributions }
850*4d495c6eSApple OSS Distributions 
851*4d495c6eSApple OSS Distributions static inline thread_qos_t
thread_qos_from_qos_class(qos_class_t cls)852*4d495c6eSApple OSS Distributions thread_qos_from_qos_class(qos_class_t cls)
853*4d495c6eSApple OSS Distributions {
854*4d495c6eSApple OSS Distributions 	switch ((unsigned int)cls) {
855*4d495c6eSApple OSS Distributions 	case QOS_CLASS_USER_INTERACTIVE: return THREAD_QOS_USER_INTERACTIVE;
856*4d495c6eSApple OSS Distributions 	case QOS_CLASS_USER_INITIATED:   return THREAD_QOS_USER_INITIATED;
857*4d495c6eSApple OSS Distributions 	case QOS_CLASS_DEFAULT:          return THREAD_QOS_DEFAULT;
858*4d495c6eSApple OSS Distributions 	case QOS_CLASS_UTILITY:          return THREAD_QOS_UTILITY;
859*4d495c6eSApple OSS Distributions 	case QOS_CLASS_BACKGROUND:       return THREAD_QOS_BACKGROUND;
860*4d495c6eSApple OSS Distributions 	case QOS_CLASS_MAINTENANCE:      return THREAD_QOS_MAINTENANCE;
861*4d495c6eSApple OSS Distributions 	default: return THREAD_QOS_UNSPECIFIED;
862*4d495c6eSApple OSS Distributions 	}
863*4d495c6eSApple OSS Distributions }
864*4d495c6eSApple OSS Distributions 
865*4d495c6eSApple OSS Distributions static void
send(mach_port_t send_port,mach_port_t reply_port,mach_port_t msg_port,qos_class_t qos,mach_msg_option_t options)866*4d495c6eSApple OSS Distributions send(
867*4d495c6eSApple OSS Distributions 	mach_port_t send_port,
868*4d495c6eSApple OSS Distributions 	mach_port_t reply_port,
869*4d495c6eSApple OSS Distributions 	mach_port_t msg_port,
870*4d495c6eSApple OSS Distributions 	qos_class_t qos,
871*4d495c6eSApple OSS Distributions 	mach_msg_option_t options)
872*4d495c6eSApple OSS Distributions {
873*4d495c6eSApple OSS Distributions 	kern_return_t ret = 0;
874*4d495c6eSApple OSS Distributions 	mach_msg_priority_t priority = (uint32_t)_pthread_qos_class_encode(qos, 0, 0);
875*4d495c6eSApple OSS Distributions 
876*4d495c6eSApple OSS Distributions 	struct test_msg send_msg = {
877*4d495c6eSApple OSS Distributions 		.header = {
878*4d495c6eSApple OSS Distributions 			.msgh_remote_port = send_port,
879*4d495c6eSApple OSS Distributions 			.msgh_local_port  = reply_port,
880*4d495c6eSApple OSS Distributions 			.msgh_bits        = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND,
881*4d495c6eSApple OSS Distributions 	    reply_port ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0, 0,
882*4d495c6eSApple OSS Distributions 	    MACH_MSGH_BITS_COMPLEX),
883*4d495c6eSApple OSS Distributions 			.msgh_id          = 0x100,
884*4d495c6eSApple OSS Distributions 			.msgh_size        = sizeof(send_msg),
885*4d495c6eSApple OSS Distributions 		},
886*4d495c6eSApple OSS Distributions 		.body = {
887*4d495c6eSApple OSS Distributions 			.msgh_descriptor_count = 1,
888*4d495c6eSApple OSS Distributions 		},
889*4d495c6eSApple OSS Distributions 		.port_descriptor = {
890*4d495c6eSApple OSS Distributions 			.name        = msg_port,
891*4d495c6eSApple OSS Distributions 			.disposition = MACH_MSG_TYPE_MOVE_RECEIVE,
892*4d495c6eSApple OSS Distributions 			.type        = MACH_MSG_PORT_DESCRIPTOR,
893*4d495c6eSApple OSS Distributions 		},
894*4d495c6eSApple OSS Distributions 		.opts = options,
895*4d495c6eSApple OSS Distributions 	};
896*4d495c6eSApple OSS Distributions 
897*4d495c6eSApple OSS Distributions 	if (msg_port == MACH_PORT_NULL) {
898*4d495c6eSApple OSS Distributions 		send_msg.body.msgh_descriptor_count = 0;
899*4d495c6eSApple OSS Distributions 	}
900*4d495c6eSApple OSS Distributions 
901*4d495c6eSApple OSS Distributions 	send_msg.qos = priority;
902*4d495c6eSApple OSS Distributions 	priority = mach_msg_priority_encode(0, thread_qos_from_qos_class(qos), 0);
903*4d495c6eSApple OSS Distributions 
904*4d495c6eSApple OSS Distributions 	mach_msg_option_t send_opts = options;
905*4d495c6eSApple OSS Distributions 	send_opts |= MACH_SEND_MSG | MACH_SEND_TIMEOUT | MACH_SEND_OVERRIDE;
906*4d495c6eSApple OSS Distributions 
907*4d495c6eSApple OSS Distributions 	ret = mach_msg(&send_msg.header, send_opts, send_msg.header.msgh_size,
908*4d495c6eSApple OSS Distributions 	    0, MACH_PORT_NULL, 10000, priority);
909*4d495c6eSApple OSS Distributions 
910*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(ret, "client mach_msg");
911*4d495c6eSApple OSS Distributions }
912*4d495c6eSApple OSS Distributions 
913*4d495c6eSApple OSS Distributions static kern_return_t
receive(mach_port_t rcv_port,mach_port_t notify_port)914*4d495c6eSApple OSS Distributions receive(
915*4d495c6eSApple OSS Distributions 	mach_port_t rcv_port,
916*4d495c6eSApple OSS Distributions 	mach_port_t notify_port)
917*4d495c6eSApple OSS Distributions {
918*4d495c6eSApple OSS Distributions 	kern_return_t ret = 0;
919*4d495c6eSApple OSS Distributions 
920*4d495c6eSApple OSS Distributions 	struct test_msg rcv_msg = {
921*4d495c6eSApple OSS Distributions 		.header = {
922*4d495c6eSApple OSS Distributions 			.msgh_remote_port = MACH_PORT_NULL,
923*4d495c6eSApple OSS Distributions 			.msgh_local_port  = rcv_port,
924*4d495c6eSApple OSS Distributions 			.msgh_size        = sizeof(rcv_msg),
925*4d495c6eSApple OSS Distributions 		},
926*4d495c6eSApple OSS Distributions 	};
927*4d495c6eSApple OSS Distributions 
928*4d495c6eSApple OSS Distributions 	T_LOG("Client: Starting sync receive\n");
929*4d495c6eSApple OSS Distributions 
930*4d495c6eSApple OSS Distributions 	ret = mach_msg(&(rcv_msg.header),
931*4d495c6eSApple OSS Distributions 	    MACH_RCV_MSG |
932*4d495c6eSApple OSS Distributions 	    MACH_RCV_TIMEOUT |
933*4d495c6eSApple OSS Distributions 	    MACH_RCV_SYNC_WAIT,
934*4d495c6eSApple OSS Distributions 	    0,
935*4d495c6eSApple OSS Distributions 	    rcv_msg.header.msgh_size,
936*4d495c6eSApple OSS Distributions 	    rcv_port,
937*4d495c6eSApple OSS Distributions 	    SEND_TIMEOUT_SECS * 1000,
938*4d495c6eSApple OSS Distributions 	    notify_port);
939*4d495c6eSApple OSS Distributions 
940*4d495c6eSApple OSS Distributions 	return ret;
941*4d495c6eSApple OSS Distributions }
942*4d495c6eSApple OSS Distributions 
943*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_get_special_reply_port,
944*4d495c6eSApple OSS Distributions     "Test get_special_reply_port and it's corner cases.")
945*4d495c6eSApple OSS Distributions {
946*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
947*4d495c6eSApple OSS Distributions 	mach_port_t new_special_reply_port;
948*4d495c6eSApple OSS Distributions 
949*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
950*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
951*4d495c6eSApple OSS Distributions 
952*4d495c6eSApple OSS Distributions 	new_special_reply_port = thread_get_special_reply_port();
953*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(new_special_reply_port), "get_thread_special_reply_port");
954*4d495c6eSApple OSS Distributions 
955*4d495c6eSApple OSS Distributions 	mach_port_destroy(mach_task_self(), special_reply_port);
956*4d495c6eSApple OSS Distributions 	mach_port_destroy(mach_task_self(), new_special_reply_port);
957*4d495c6eSApple OSS Distributions 
958*4d495c6eSApple OSS Distributions 	new_special_reply_port = thread_get_special_reply_port();
959*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(new_special_reply_port), "get_thread_special_reply_port");
960*4d495c6eSApple OSS Distributions 
961*4d495c6eSApple OSS Distributions 	T_END;
962*4d495c6eSApple OSS Distributions }
963*4d495c6eSApple OSS Distributions 
964*4d495c6eSApple OSS Distributions static void *
qos_client_send_to_intransit(void * arg __unused)965*4d495c6eSApple OSS Distributions qos_client_send_to_intransit(void *arg __unused)
966*4d495c6eSApple OSS Distributions {
967*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
968*4d495c6eSApple OSS Distributions 	mach_port_t msg_port;
969*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
970*4d495c6eSApple OSS Distributions 
971*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
972*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
973*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
974*4d495c6eSApple OSS Distributions 
975*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
976*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
977*4d495c6eSApple OSS Distributions 
978*4d495c6eSApple OSS Distributions 	/* Create a rcv right to send in a msg */
979*4d495c6eSApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(),
980*4d495c6eSApple OSS Distributions 	    MACH_PORT_RIGHT_RECEIVE,
981*4d495c6eSApple OSS Distributions 	    &msg_port);
982*4d495c6eSApple OSS Distributions 
983*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client mach_port_allocate");
984*4d495c6eSApple OSS Distributions 
985*4d495c6eSApple OSS Distributions 	kr = mach_port_insert_right(mach_task_self(),
986*4d495c6eSApple OSS Distributions 	    msg_port,
987*4d495c6eSApple OSS Distributions 	    msg_port,
988*4d495c6eSApple OSS Distributions 	    MACH_MSG_TYPE_MAKE_SEND);
989*4d495c6eSApple OSS Distributions 
990*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client mach_port_insert_right");
991*4d495c6eSApple OSS Distributions 
992*4d495c6eSApple OSS Distributions 	/* Send an empty msg on the port to fire the WL thread */
993*4d495c6eSApple OSS Distributions 	send(qos_send_port, MACH_PORT_NULL, MACH_PORT_NULL,
994*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], 0);
995*4d495c6eSApple OSS Distributions 
996*4d495c6eSApple OSS Distributions 	/* Sleep 3 seconds for the server to start */
997*4d495c6eSApple OSS Distributions 	sleep(3);
998*4d495c6eSApple OSS Distributions 
999*4d495c6eSApple OSS Distributions 	/* Send the message with msg port as in-transit port, this msg will not be dequeued */
1000*4d495c6eSApple OSS Distributions 	send(qos_send_port, MACH_PORT_NULL, msg_port,
1001*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], 0);
1002*4d495c6eSApple OSS Distributions 
1003*4d495c6eSApple OSS Distributions 	/* Send 5 messages to msg port to make sure the port is full */
1004*4d495c6eSApple OSS Distributions 	for (int i = 0; i < 5; i++) {
1005*4d495c6eSApple OSS Distributions 		send(msg_port, MACH_PORT_NULL, MACH_PORT_NULL,
1006*4d495c6eSApple OSS Distributions 		    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], 0);
1007*4d495c6eSApple OSS Distributions 	}
1008*4d495c6eSApple OSS Distributions 
1009*4d495c6eSApple OSS Distributions 	T_LOG("Sent 5 msgs, now trying to send sync ipc message, which will block with a timeout\n");
1010*4d495c6eSApple OSS Distributions 	/* Send the message to the in-transit port, it should block and override the rcv's workloop */
1011*4d495c6eSApple OSS Distributions 	send(msg_port, special_reply_port, MACH_PORT_NULL,
1012*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1013*4d495c6eSApple OSS Distributions 	T_LOG("Client done sending messages, now waiting for server to end the test");
1014*4d495c6eSApple OSS Distributions 
1015*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1016*4d495c6eSApple OSS Distributions 	return NULL;
1017*4d495c6eSApple OSS Distributions }
1018*4d495c6eSApple OSS Distributions 
1019*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_to_intransit_with_thr_pri,
1020*4d495c6eSApple OSS Distributions     "Send synchronous messages from a pri thread to an intransit port")
1021*4d495c6eSApple OSS Distributions {
1022*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_send_to_intransit);
1023*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1024*4d495c6eSApple OSS Distributions }
1025*4d495c6eSApple OSS Distributions 
1026*4d495c6eSApple OSS Distributions static pthread_t
thread_create_at_qos(qos_class_t qos,void * (* function)(void *))1027*4d495c6eSApple OSS Distributions thread_create_at_qos(qos_class_t qos, void * (*function)(void *))
1028*4d495c6eSApple OSS Distributions {
1029*4d495c6eSApple OSS Distributions 	qos_class_t qos_thread;
1030*4d495c6eSApple OSS Distributions 	pthread_t thread;
1031*4d495c6eSApple OSS Distributions 	pthread_attr_t attr;
1032*4d495c6eSApple OSS Distributions 	int ret;
1033*4d495c6eSApple OSS Distributions 
1034*4d495c6eSApple OSS Distributions 	ret = setpriority(PRIO_DARWIN_ROLE, 0, PRIO_DARWIN_ROLE_UI_FOCAL);
1035*4d495c6eSApple OSS Distributions 	if (ret != 0) {
1036*4d495c6eSApple OSS Distributions 		T_LOG("set priority failed\n");
1037*4d495c6eSApple OSS Distributions 	}
1038*4d495c6eSApple OSS Distributions 
1039*4d495c6eSApple OSS Distributions 	pthread_attr_init(&attr);
1040*4d495c6eSApple OSS Distributions 	pthread_attr_set_qos_class_np(&attr, qos, 0);
1041*4d495c6eSApple OSS Distributions 	pthread_create(&thread, &attr, function, NULL);
1042*4d495c6eSApple OSS Distributions 
1043*4d495c6eSApple OSS Distributions 	T_LOG("pthread created\n");
1044*4d495c6eSApple OSS Distributions 	pthread_get_qos_class_np(thread, &qos_thread, NULL);
1045*4d495c6eSApple OSS Distributions 	T_EXPECT_EQ(qos_thread, (qos_class_t)qos, NULL);
1046*4d495c6eSApple OSS Distributions 	return thread;
1047*4d495c6eSApple OSS Distributions }
1048*4d495c6eSApple OSS Distributions 
1049*4d495c6eSApple OSS Distributions static void *
qos_send_and_sync_rcv(void * arg __unused)1050*4d495c6eSApple OSS Distributions qos_send_and_sync_rcv(void *arg __unused)
1051*4d495c6eSApple OSS Distributions {
1052*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1053*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1054*4d495c6eSApple OSS Distributions 
1055*4d495c6eSApple OSS Distributions 	T_LOG("Client: from created thread\n");
1056*4d495c6eSApple OSS Distributions 	T_EXPECT_EFFECTIVE_QOS_EQ(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
1057*4d495c6eSApple OSS Distributions 	    "pthread QoS should be %s", g_expected_qos_name[ENV_QOS_AFTER_OVERRIDE]);
1058*4d495c6eSApple OSS Distributions 
1059*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1060*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1061*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1062*4d495c6eSApple OSS Distributions 
1063*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
1064*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
1065*4d495c6eSApple OSS Distributions 
1066*4d495c6eSApple OSS Distributions 	/* enqueue two messages to make sure that mqueue is not empty */
1067*4d495c6eSApple OSS Distributions 	send(qos_send_port, MACH_PORT_NULL, MACH_PORT_NULL,
1068*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_QUEUE_OVERRIDE], 0);
1069*4d495c6eSApple OSS Distributions 
1070*4d495c6eSApple OSS Distributions 	send(qos_send_port, MACH_PORT_NULL, MACH_PORT_NULL,
1071*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_QUEUE_OVERRIDE], 0);
1072*4d495c6eSApple OSS Distributions 
1073*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1074*4d495c6eSApple OSS Distributions 
1075*4d495c6eSApple OSS Distributions 	/* sync wait on msg port */
1076*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1077*4d495c6eSApple OSS Distributions 
1078*4d495c6eSApple OSS Distributions 	T_LOG("Client done doing sync rcv, now waiting for server to end the test");
1079*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1080*4d495c6eSApple OSS Distributions 
1081*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1082*4d495c6eSApple OSS Distributions 	return NULL;
1083*4d495c6eSApple OSS Distributions }
1084*4d495c6eSApple OSS Distributions 
1085*4d495c6eSApple OSS Distributions static void *
qos_sync_rcv(void * arg __unused)1086*4d495c6eSApple OSS Distributions qos_sync_rcv(void *arg __unused)
1087*4d495c6eSApple OSS Distributions {
1088*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1089*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1090*4d495c6eSApple OSS Distributions 
1091*4d495c6eSApple OSS Distributions 	T_LOG("Client: from created thread\n");
1092*4d495c6eSApple OSS Distributions 
1093*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1094*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1095*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1096*4d495c6eSApple OSS Distributions 
1097*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
1098*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
1099*4d495c6eSApple OSS Distributions 
1100*4d495c6eSApple OSS Distributions 	/* enqueue two messages to make sure that mqueue is not empty */
1101*4d495c6eSApple OSS Distributions 	send(qos_send_port, MACH_PORT_NULL, MACH_PORT_NULL,
1102*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_QUEUE_OVERRIDE], 0);
1103*4d495c6eSApple OSS Distributions 
1104*4d495c6eSApple OSS Distributions 	sleep(RECV_TIMEOUT_SECS);
1105*4d495c6eSApple OSS Distributions 
1106*4d495c6eSApple OSS Distributions 	/* sync wait on msg port */
1107*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1108*4d495c6eSApple OSS Distributions 
1109*4d495c6eSApple OSS Distributions 	T_LOG("Client done doing sync rcv, now waiting for server to end the test");
1110*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1111*4d495c6eSApple OSS Distributions 
1112*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1113*4d495c6eSApple OSS Distributions 	return NULL;
1114*4d495c6eSApple OSS Distributions }
1115*4d495c6eSApple OSS Distributions 
1116*4d495c6eSApple OSS Distributions static void
thread_wait_to_block(mach_port_t thread_port)1117*4d495c6eSApple OSS Distributions thread_wait_to_block(mach_port_t thread_port)
1118*4d495c6eSApple OSS Distributions {
1119*4d495c6eSApple OSS Distributions 	thread_extended_info_data_t extended_info;
1120*4d495c6eSApple OSS Distributions 	kern_return_t kr;
1121*4d495c6eSApple OSS Distributions 
1122*4d495c6eSApple OSS Distributions 	while (1) {
1123*4d495c6eSApple OSS Distributions 		mach_msg_type_number_t count = THREAD_EXTENDED_INFO_COUNT;
1124*4d495c6eSApple OSS Distributions 		kr = thread_info(thread_port, THREAD_EXTENDED_INFO,
1125*4d495c6eSApple OSS Distributions 		    (thread_info_t)&extended_info, &count);
1126*4d495c6eSApple OSS Distributions 
1127*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "thread_info");
1128*4d495c6eSApple OSS Distributions 
1129*4d495c6eSApple OSS Distributions 		if (extended_info.pth_run_state == TH_STATE_WAITING) {
1130*4d495c6eSApple OSS Distributions 			T_LOG("Target thread blocked\n");
1131*4d495c6eSApple OSS Distributions 			break;
1132*4d495c6eSApple OSS Distributions 		}
1133*4d495c6eSApple OSS Distributions 		thread_switch(thread_port, SWITCH_OPTION_DEPRESS, 0);
1134*4d495c6eSApple OSS Distributions 	}
1135*4d495c6eSApple OSS Distributions }
1136*4d495c6eSApple OSS Distributions 
1137*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_sync_and_sync_rcv,
1138*4d495c6eSApple OSS Distributions     "Send messages and syncronously wait for rcv")
1139*4d495c6eSApple OSS Distributions {
1140*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_send_and_sync_rcv);
1141*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1142*4d495c6eSApple OSS Distributions }
1143*4d495c6eSApple OSS Distributions 
1144*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_sync_rcv_qos_change,
1145*4d495c6eSApple OSS Distributions     "Send messages and syncronously wait for rcv and change qos of waiting thread")
1146*4d495c6eSApple OSS Distributions {
1147*4d495c6eSApple OSS Distributions 	pthread_t rcv_thread;
1148*4d495c6eSApple OSS Distributions 
1149*4d495c6eSApple OSS Distributions 	rcv_thread = thread_create_at_qos(g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], qos_sync_rcv);
1150*4d495c6eSApple OSS Distributions 
1151*4d495c6eSApple OSS Distributions 	T_LOG("Waiting for %d seconds before changing qos of rcv thread", SEND_TIMEOUT_SECS);
1152*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1153*4d495c6eSApple OSS Distributions 
1154*4d495c6eSApple OSS Distributions 	/* Wait for the thread to block */
1155*4d495c6eSApple OSS Distributions 	thread_wait_to_block(pthread_mach_thread_np(rcv_thread));
1156*4d495c6eSApple OSS Distributions 
1157*4d495c6eSApple OSS Distributions 	/* Update the rcv thread's qos */
1158*4d495c6eSApple OSS Distributions 	pthread_override_qos_class_start_np(rcv_thread, g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1159*4d495c6eSApple OSS Distributions 
1160*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1161*4d495c6eSApple OSS Distributions }
1162*4d495c6eSApple OSS Distributions 
1163*4d495c6eSApple OSS Distributions static void *
qos_client_send_sync_msg_and_test_link(void * arg)1164*4d495c6eSApple OSS Distributions qos_client_send_sync_msg_and_test_link(void *arg)
1165*4d495c6eSApple OSS Distributions {
1166*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1167*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1168*4d495c6eSApple OSS Distributions 	boolean_t in_effect = FALSE;
1169*4d495c6eSApple OSS Distributions 	kern_return_t kr;
1170*4d495c6eSApple OSS Distributions 	unsigned long expected_result = (unsigned long) arg;
1171*4d495c6eSApple OSS Distributions 
1172*4d495c6eSApple OSS Distributions 	kr = bootstrap_look_up(bootstrap_port,
1173*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1174*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1175*4d495c6eSApple OSS Distributions 
1176*4d495c6eSApple OSS Distributions 	/* start monitoring sync ipc link */
1177*4d495c6eSApple OSS Distributions 	kr = mach_sync_ipc_link_monitoring_start(&special_reply_port);
1178*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_sync_ipc_link_monitoring_start");
1179*4d495c6eSApple OSS Distributions 
1180*4d495c6eSApple OSS Distributions 	/* Send the message to msg port */
1181*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1182*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1183*4d495c6eSApple OSS Distributions 
1184*4d495c6eSApple OSS Distributions 	/*
1185*4d495c6eSApple OSS Distributions 	 * wait for the reply
1186*4d495c6eSApple OSS Distributions 	 * some tests do not send a msg back so the receive
1187*4d495c6eSApple OSS Distributions 	 * might fail
1188*4d495c6eSApple OSS Distributions 	 */
1189*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1190*4d495c6eSApple OSS Distributions 
1191*4d495c6eSApple OSS Distributions 	/* stop monitoring link */
1192*4d495c6eSApple OSS Distributions 	kr = mach_sync_ipc_link_monitoring_stop(special_reply_port, &in_effect);
1193*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_sync_ipc_link_monitoring_stop");
1194*4d495c6eSApple OSS Distributions 
1195*4d495c6eSApple OSS Distributions 	if (!in_effect) {
1196*4d495c6eSApple OSS Distributions 		T_LOG("Link was broken");
1197*4d495c6eSApple OSS Distributions 	} else {
1198*4d495c6eSApple OSS Distributions 		T_LOG("Link correct");
1199*4d495c6eSApple OSS Distributions 	}
1200*4d495c6eSApple OSS Distributions 
1201*4d495c6eSApple OSS Distributions 	if (expected_result == 1) {
1202*4d495c6eSApple OSS Distributions 		T_ASSERT_TRUE(in_effect, "special reply port link after rcv");
1203*4d495c6eSApple OSS Distributions 	} else {
1204*4d495c6eSApple OSS Distributions 		T_ASSERT_FALSE(in_effect, "special reply port link after rcv");
1205*4d495c6eSApple OSS Distributions 	}
1206*4d495c6eSApple OSS Distributions 	T_END;
1207*4d495c6eSApple OSS Distributions }
1208*4d495c6eSApple OSS Distributions 
1209*4d495c6eSApple OSS Distributions static void *
qos_client_send_2sync_msg_and_test_link(void * arg)1210*4d495c6eSApple OSS Distributions qos_client_send_2sync_msg_and_test_link(void *arg)
1211*4d495c6eSApple OSS Distributions {
1212*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1213*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1214*4d495c6eSApple OSS Distributions 	boolean_t in_effect = FALSE;
1215*4d495c6eSApple OSS Distributions 	kern_return_t kr;
1216*4d495c6eSApple OSS Distributions 	unsigned long expected_result = (unsigned long) arg;
1217*4d495c6eSApple OSS Distributions 
1218*4d495c6eSApple OSS Distributions 	kr = bootstrap_look_up(bootstrap_port,
1219*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1220*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1221*4d495c6eSApple OSS Distributions 
1222*4d495c6eSApple OSS Distributions 	/* start monitoring sync ipc link */
1223*4d495c6eSApple OSS Distributions 	kr = mach_sync_ipc_link_monitoring_start(&special_reply_port);
1224*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_sync_ipc_link_monitoring_start");
1225*4d495c6eSApple OSS Distributions 
1226*4d495c6eSApple OSS Distributions 	/* Send the first message to msg port */
1227*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1228*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1229*4d495c6eSApple OSS Distributions 
1230*4d495c6eSApple OSS Distributions 	/* wait for the reply */
1231*4d495c6eSApple OSS Distributions 	kr = receive(special_reply_port, qos_send_port);
1232*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "receive");
1233*4d495c6eSApple OSS Distributions 
1234*4d495c6eSApple OSS Distributions 	/* Send the second message to msg port */
1235*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1236*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1237*4d495c6eSApple OSS Distributions 
1238*4d495c6eSApple OSS Distributions 	/* wait for the reply */
1239*4d495c6eSApple OSS Distributions 	kr = receive(special_reply_port, qos_send_port);
1240*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "receive");
1241*4d495c6eSApple OSS Distributions 
1242*4d495c6eSApple OSS Distributions 	/* stop monitoring link */
1243*4d495c6eSApple OSS Distributions 	kr = mach_sync_ipc_link_monitoring_stop(special_reply_port, &in_effect);
1244*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_sync_ipc_link_monitoring_stop");
1245*4d495c6eSApple OSS Distributions 
1246*4d495c6eSApple OSS Distributions 	if (!in_effect) {
1247*4d495c6eSApple OSS Distributions 		T_LOG("Link was broken");
1248*4d495c6eSApple OSS Distributions 	} else {
1249*4d495c6eSApple OSS Distributions 		T_LOG("Link correct");
1250*4d495c6eSApple OSS Distributions 	}
1251*4d495c6eSApple OSS Distributions 
1252*4d495c6eSApple OSS Distributions 	if (expected_result == 1) {
1253*4d495c6eSApple OSS Distributions 		T_ASSERT_TRUE(in_effect, "special reply port link after rcv");
1254*4d495c6eSApple OSS Distributions 	} else {
1255*4d495c6eSApple OSS Distributions 		T_ASSERT_FALSE(in_effect, "special reply port link after rcv");
1256*4d495c6eSApple OSS Distributions 	}
1257*4d495c6eSApple OSS Distributions 	T_END;
1258*4d495c6eSApple OSS Distributions }
1259*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_sync_msg_with_link_check_correct_server,
1260*4d495c6eSApple OSS Distributions     "Send sync message, wait for reply and check sync ipc link")
1261*4d495c6eSApple OSS Distributions {
1262*4d495c6eSApple OSS Distributions 	pthread_t thread;
1263*4d495c6eSApple OSS Distributions 	pthread_attr_t attr;
1264*4d495c6eSApple OSS Distributions 	unsigned long expected_result = 1;
1265*4d495c6eSApple OSS Distributions 
1266*4d495c6eSApple OSS Distributions 	pthread_attr_init(&attr);
1267*4d495c6eSApple OSS Distributions 	pthread_create(&thread, &attr, qos_client_send_sync_msg_and_test_link, (void *)expected_result);
1268*4d495c6eSApple OSS Distributions 
1269*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1270*4d495c6eSApple OSS Distributions }
1271*4d495c6eSApple OSS Distributions 
1272*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_sync_msg_with_link_check_incorrect_server,
1273*4d495c6eSApple OSS Distributions     "Send sync message, wait for reply and check sync ipc link")
1274*4d495c6eSApple OSS Distributions {
1275*4d495c6eSApple OSS Distributions 	pthread_t thread;
1276*4d495c6eSApple OSS Distributions 	pthread_attr_t attr;
1277*4d495c6eSApple OSS Distributions 	unsigned long expected_result = 0;
1278*4d495c6eSApple OSS Distributions 
1279*4d495c6eSApple OSS Distributions 	pthread_attr_init(&attr);
1280*4d495c6eSApple OSS Distributions 	pthread_create(&thread, &attr, qos_client_send_sync_msg_and_test_link, (void *)expected_result);
1281*4d495c6eSApple OSS Distributions 
1282*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1283*4d495c6eSApple OSS Distributions }
1284*4d495c6eSApple OSS Distributions 
1285*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_2sync_msg_with_link_check_correct_server,
1286*4d495c6eSApple OSS Distributions     "Send sync message, wait for reply and check sync ipc link")
1287*4d495c6eSApple OSS Distributions {
1288*4d495c6eSApple OSS Distributions 	pthread_t thread;
1289*4d495c6eSApple OSS Distributions 	pthread_attr_t attr;
1290*4d495c6eSApple OSS Distributions 	unsigned long expected_result = 1;
1291*4d495c6eSApple OSS Distributions 
1292*4d495c6eSApple OSS Distributions 	pthread_attr_init(&attr);
1293*4d495c6eSApple OSS Distributions 	pthread_create(&thread, &attr, qos_client_send_2sync_msg_and_test_link, (void *)expected_result);
1294*4d495c6eSApple OSS Distributions 
1295*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1296*4d495c6eSApple OSS Distributions }
1297*4d495c6eSApple OSS Distributions 
1298*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_2sync_msg_with_link_check_incorrect_server,
1299*4d495c6eSApple OSS Distributions     "Send sync message, wait for reply and check sync ipc link")
1300*4d495c6eSApple OSS Distributions {
1301*4d495c6eSApple OSS Distributions 	pthread_t thread;
1302*4d495c6eSApple OSS Distributions 	pthread_attr_t attr;
1303*4d495c6eSApple OSS Distributions 	unsigned long expected_result = 0;
1304*4d495c6eSApple OSS Distributions 
1305*4d495c6eSApple OSS Distributions 	pthread_attr_init(&attr);
1306*4d495c6eSApple OSS Distributions 	pthread_create(&thread, &attr, qos_client_send_2sync_msg_and_test_link, (void *)expected_result);
1307*4d495c6eSApple OSS Distributions 
1308*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1309*4d495c6eSApple OSS Distributions }
1310*4d495c6eSApple OSS Distributions 
1311*4d495c6eSApple OSS Distributions static void *
qos_client_send_sync_msg(void * arg __unused)1312*4d495c6eSApple OSS Distributions qos_client_send_sync_msg(void *arg __unused)
1313*4d495c6eSApple OSS Distributions {
1314*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1315*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1316*4d495c6eSApple OSS Distributions 
1317*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1318*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1319*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1320*4d495c6eSApple OSS Distributions 
1321*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
1322*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
1323*4d495c6eSApple OSS Distributions 
1324*4d495c6eSApple OSS Distributions 	/* Send the message to msg port */
1325*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1326*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1327*4d495c6eSApple OSS Distributions 
1328*4d495c6eSApple OSS Distributions 	/* wait for the reply */
1329*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1330*4d495c6eSApple OSS Distributions 
1331*4d495c6eSApple OSS Distributions 	T_LOG("Client done sending messages, now waiting for server to end the test");
1332*4d495c6eSApple OSS Distributions 	sleep(2 * SEND_TIMEOUT_SECS);
1333*4d495c6eSApple OSS Distributions 
1334*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1335*4d495c6eSApple OSS Distributions 	return NULL;
1336*4d495c6eSApple OSS Distributions }
1337*4d495c6eSApple OSS Distributions 
1338*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_sync_msg_with_pri,
1339*4d495c6eSApple OSS Distributions     "Send sync message and wait for reply")
1340*4d495c6eSApple OSS Distributions {
1341*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_send_sync_msg);
1342*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1343*4d495c6eSApple OSS Distributions }
1344*4d495c6eSApple OSS Distributions 
1345*4d495c6eSApple OSS Distributions static void *
qos_client_kernel_upcall_send_sync_msg(void * arg __unused)1346*4d495c6eSApple OSS Distributions qos_client_kernel_upcall_send_sync_msg(void *arg __unused)
1347*4d495c6eSApple OSS Distributions {
1348*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1349*4d495c6eSApple OSS Distributions 
1350*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1351*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1352*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1353*4d495c6eSApple OSS Distributions 
1354*4d495c6eSApple OSS Distributions 	/* Call task_test_sync_upcall to perform a sync kernel upcall */
1355*4d495c6eSApple OSS Distributions 	kr = task_test_sync_upcall(mach_task_self(), qos_send_port);
1356*4d495c6eSApple OSS Distributions 	if (kr == KERN_NOT_SUPPORTED) {
1357*4d495c6eSApple OSS Distributions 		T_QUIET; T_SKIP("QOS Client Kernel Upcall test called on release kernel, skipping\n");
1358*4d495c6eSApple OSS Distributions 	}
1359*4d495c6eSApple OSS Distributions 
1360*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "task_test_sync_upcall");
1361*4d495c6eSApple OSS Distributions 
1362*4d495c6eSApple OSS Distributions 	T_LOG("Client done doing upcall, now waiting for server to end the test");
1363*4d495c6eSApple OSS Distributions 	sleep(2 * SEND_TIMEOUT_SECS);
1364*4d495c6eSApple OSS Distributions 
1365*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1366*4d495c6eSApple OSS Distributions 	return NULL;
1367*4d495c6eSApple OSS Distributions }
1368*4d495c6eSApple OSS Distributions 
1369*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_kernel_upcall_sync_msg_with_pri,
1370*4d495c6eSApple OSS Distributions     "Send Kernel upcall sync message and wait for reply")
1371*4d495c6eSApple OSS Distributions {
1372*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_kernel_upcall_send_sync_msg);
1373*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1374*4d495c6eSApple OSS Distributions }
1375*4d495c6eSApple OSS Distributions 
1376*4d495c6eSApple OSS Distributions static void *
qos_client_kernel_upcall_send_async_msg(void * arg __unused)1377*4d495c6eSApple OSS Distributions qos_client_kernel_upcall_send_async_msg(void *arg __unused)
1378*4d495c6eSApple OSS Distributions {
1379*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1380*4d495c6eSApple OSS Distributions 
1381*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1382*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1383*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1384*4d495c6eSApple OSS Distributions 
1385*4d495c6eSApple OSS Distributions 	/* Call task_test_async_upcall_propagation to perform an async kernel upcall */
1386*4d495c6eSApple OSS Distributions 	kr = task_test_async_upcall_propagation(mach_task_self(), qos_send_port, THREAD_QOS_UTILITY, USR_THROTTLE_LEVEL_TIER0);
1387*4d495c6eSApple OSS Distributions 	if (kr == KERN_NOT_SUPPORTED) {
1388*4d495c6eSApple OSS Distributions 		T_QUIET; T_SKIP("QOS Client Kernel Upcall test called on release kernel, skipping\n");
1389*4d495c6eSApple OSS Distributions 	}
1390*4d495c6eSApple OSS Distributions 
1391*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "task_test_async_upcall_propagation");
1392*4d495c6eSApple OSS Distributions 
1393*4d495c6eSApple OSS Distributions 	T_LOG("Client done doing upcall, now waiting for server to end the test");
1394*4d495c6eSApple OSS Distributions 	sleep(2 * SEND_TIMEOUT_SECS);
1395*4d495c6eSApple OSS Distributions 
1396*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1397*4d495c6eSApple OSS Distributions 	return NULL;
1398*4d495c6eSApple OSS Distributions }
1399*4d495c6eSApple OSS Distributions 
1400*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_iotier_client_send_kernel_upcall_async_msg,
1401*4d495c6eSApple OSS Distributions     "Send Kernel upcall async message")
1402*4d495c6eSApple OSS Distributions {
1403*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_kernel_upcall_send_async_msg);
1404*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1405*4d495c6eSApple OSS Distributions }
1406*4d495c6eSApple OSS Distributions 
1407*4d495c6eSApple OSS Distributions static void *
qos_client_send_two_sync_msg_high_qos(void * arg __unused)1408*4d495c6eSApple OSS Distributions qos_client_send_two_sync_msg_high_qos(void *arg __unused)
1409*4d495c6eSApple OSS Distributions {
1410*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1411*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1412*4d495c6eSApple OSS Distributions 
1413*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1414*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1415*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1416*4d495c6eSApple OSS Distributions 
1417*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
1418*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
1419*4d495c6eSApple OSS Distributions 
1420*4d495c6eSApple OSS Distributions 	/* Send the message to msg port */
1421*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1422*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_AFTER_OVERRIDE], 0);
1423*4d495c6eSApple OSS Distributions 
1424*4d495c6eSApple OSS Distributions 	/* wait for the reply */
1425*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1426*4d495c6eSApple OSS Distributions 
1427*4d495c6eSApple OSS Distributions 	T_LOG("Client done sending messages, now waiting for server to end the test");
1428*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1429*4d495c6eSApple OSS Distributions 
1430*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1431*4d495c6eSApple OSS Distributions 	return NULL;
1432*4d495c6eSApple OSS Distributions }
1433*4d495c6eSApple OSS Distributions 
1434*4d495c6eSApple OSS Distributions static void *
qos_client_send_two_sync_msg_low_qos(void * arg __unused)1435*4d495c6eSApple OSS Distributions qos_client_send_two_sync_msg_low_qos(void *arg __unused)
1436*4d495c6eSApple OSS Distributions {
1437*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1438*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1439*4d495c6eSApple OSS Distributions 
1440*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1441*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1442*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1443*4d495c6eSApple OSS Distributions 
1444*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
1445*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
1446*4d495c6eSApple OSS Distributions 
1447*4d495c6eSApple OSS Distributions 	/* Send the message to msg port */
1448*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1449*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], 0);
1450*4d495c6eSApple OSS Distributions 
1451*4d495c6eSApple OSS Distributions 	/* wait for the reply */
1452*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1453*4d495c6eSApple OSS Distributions 
1454*4d495c6eSApple OSS Distributions 	T_LOG("Client done sending messages, now waiting for server to end the test");
1455*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1456*4d495c6eSApple OSS Distributions 
1457*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1458*4d495c6eSApple OSS Distributions 	return NULL;
1459*4d495c6eSApple OSS Distributions }
1460*4d495c6eSApple OSS Distributions 
1461*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_two_sync_msg_with_thr_pri,
1462*4d495c6eSApple OSS Distributions     "Send messages sync msgs from 2 threads at given thread pri")
1463*4d495c6eSApple OSS Distributions {
1464*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_send_two_sync_msg_high_qos);
1465*4d495c6eSApple OSS Distributions 	sleep(INTERMITTENT_TIMEOUT_SEC);
1466*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], qos_client_send_two_sync_msg_low_qos);
1467*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1468*4d495c6eSApple OSS Distributions }
1469*4d495c6eSApple OSS Distributions 
1470*4d495c6eSApple OSS Distributions static mach_port_t other_thread_reply_port = MACH_PORT_NULL;
1471*4d495c6eSApple OSS Distributions static void *
qos_client_destroy_other_threads_port(void * arg __unused)1472*4d495c6eSApple OSS Distributions qos_client_destroy_other_threads_port(void *arg __unused)
1473*4d495c6eSApple OSS Distributions {
1474*4d495c6eSApple OSS Distributions 	T_LOG("Waiting 6 seconds before destroying other thread's reply port");
1475*4d495c6eSApple OSS Distributions 	sleep(SEND_TIMEOUT_SECS);
1476*4d495c6eSApple OSS Distributions 
1477*4d495c6eSApple OSS Distributions 	T_LOG("Destroying other thread's special reply port ");
1478*4d495c6eSApple OSS Distributions 	mach_port_destroy(mach_task_self(), other_thread_reply_port);
1479*4d495c6eSApple OSS Distributions 
1480*4d495c6eSApple OSS Distributions 	T_LOG("Other thread done destroying ");
1481*4d495c6eSApple OSS Distributions 	sleep(3 * SEND_TIMEOUT_SECS);
1482*4d495c6eSApple OSS Distributions 
1483*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1484*4d495c6eSApple OSS Distributions 	return NULL;
1485*4d495c6eSApple OSS Distributions }
1486*4d495c6eSApple OSS Distributions 
1487*4d495c6eSApple OSS Distributions static void *
qos_client_create_sepcial_reply_and_spawn_thread(void * arg __unused)1488*4d495c6eSApple OSS Distributions qos_client_create_sepcial_reply_and_spawn_thread(void *arg __unused)
1489*4d495c6eSApple OSS Distributions {
1490*4d495c6eSApple OSS Distributions 	mach_port_t qos_send_port;
1491*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port;
1492*4d495c6eSApple OSS Distributions 
1493*4d495c6eSApple OSS Distributions 	kern_return_t kr = bootstrap_look_up(bootstrap_port,
1494*4d495c6eSApple OSS Distributions 	    KEVENT_QOS_SERVICE_NAME, &qos_send_port);
1495*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1496*4d495c6eSApple OSS Distributions 
1497*4d495c6eSApple OSS Distributions 	special_reply_port = thread_get_special_reply_port();
1498*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(special_reply_port), "get_thread_special_reply_port");
1499*4d495c6eSApple OSS Distributions 
1500*4d495c6eSApple OSS Distributions 	other_thread_reply_port = special_reply_port;
1501*4d495c6eSApple OSS Distributions 
1502*4d495c6eSApple OSS Distributions 	/* Send an async message */
1503*4d495c6eSApple OSS Distributions 	send(qos_send_port, MACH_PORT_NULL, MACH_PORT_NULL,
1504*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], 0);
1505*4d495c6eSApple OSS Distributions 
1506*4d495c6eSApple OSS Distributions 	/* Send the sync ipc message */
1507*4d495c6eSApple OSS Distributions 	send(qos_send_port, special_reply_port, MACH_PORT_NULL,
1508*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE], 0);
1509*4d495c6eSApple OSS Distributions 
1510*4d495c6eSApple OSS Distributions 	/* Create a new thread to send the sync message on our special reply port */
1511*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_destroy_other_threads_port);
1512*4d495c6eSApple OSS Distributions 
1513*4d495c6eSApple OSS Distributions 	/* Client starting to receive message */
1514*4d495c6eSApple OSS Distributions 	receive(special_reply_port, qos_send_port);
1515*4d495c6eSApple OSS Distributions 
1516*4d495c6eSApple OSS Distributions 	sleep(3 * SEND_TIMEOUT_SECS);
1517*4d495c6eSApple OSS Distributions 
1518*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1519*4d495c6eSApple OSS Distributions 	return NULL;
1520*4d495c6eSApple OSS Distributions }
1521*4d495c6eSApple OSS Distributions 
1522*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_two_msg_and_destroy,
1523*4d495c6eSApple OSS Distributions     "Send a message with another threads special reply port while that thread destroys the port")
1524*4d495c6eSApple OSS Distributions {
1525*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE], qos_client_create_sepcial_reply_and_spawn_thread);
1526*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1527*4d495c6eSApple OSS Distributions }
1528*4d495c6eSApple OSS Distributions 
1529*4d495c6eSApple OSS Distributions static mach_port_t send_complex_connection_port = MACH_PORT_NULL;
1530*4d495c6eSApple OSS Distributions 
1531*4d495c6eSApple OSS Distributions static void *
qos_client_send_complex_msg_to_service_port(void * arg __unused)1532*4d495c6eSApple OSS Distributions qos_client_send_complex_msg_to_service_port(void *arg __unused)
1533*4d495c6eSApple OSS Distributions {
1534*4d495c6eSApple OSS Distributions 	mach_port_t svc_port, tsr_port, conn_port;
1535*4d495c6eSApple OSS Distributions 	kern_return_t kr;
1536*4d495c6eSApple OSS Distributions 
1537*4d495c6eSApple OSS Distributions 	kr = bootstrap_look_up(bootstrap_port, KEVENT_QOS_SERVICE_NAME, &svc_port);
1538*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "client bootstrap_look_up");
1539*4d495c6eSApple OSS Distributions 
1540*4d495c6eSApple OSS Distributions 	tsr_port = thread_get_special_reply_port();
1541*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(tsr_port), "get_thread_special_reply_port");
1542*4d495c6eSApple OSS Distributions 
1543*4d495c6eSApple OSS Distributions 	conn_port = send_complex_connection_port;
1544*4d495c6eSApple OSS Distributions 
1545*4d495c6eSApple OSS Distributions 	T_LOG("Sending to the service port with a sync IPC");
1546*4d495c6eSApple OSS Distributions 	send(svc_port, tsr_port, conn_port,
1547*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE],
1548*4d495c6eSApple OSS Distributions 	    MACH_SEND_PROPAGATE_QOS);
1549*4d495c6eSApple OSS Distributions 
1550*4d495c6eSApple OSS Distributions 	receive(tsr_port, svc_port);
1551*4d495c6eSApple OSS Distributions 
1552*4d495c6eSApple OSS Distributions 	sleep(3 * SEND_TIMEOUT_SECS);
1553*4d495c6eSApple OSS Distributions 
1554*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1555*4d495c6eSApple OSS Distributions 	return NULL;
1556*4d495c6eSApple OSS Distributions }
1557*4d495c6eSApple OSS Distributions 
1558*4d495c6eSApple OSS Distributions static void *
qos_client_send_to_connection_then_service_port(void * arg __unused)1559*4d495c6eSApple OSS Distributions qos_client_send_to_connection_then_service_port(void *arg __unused)
1560*4d495c6eSApple OSS Distributions {
1561*4d495c6eSApple OSS Distributions 	mach_port_t tsr_port, conn_port;
1562*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
1563*4d495c6eSApple OSS Distributions 		.flags = MPO_INSERT_SEND_RIGHT,
1564*4d495c6eSApple OSS Distributions 	};
1565*4d495c6eSApple OSS Distributions 	kern_return_t kr;
1566*4d495c6eSApple OSS Distributions 
1567*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0ull, &conn_port);
1568*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_construct");
1569*4d495c6eSApple OSS Distributions 	send_complex_connection_port = conn_port;
1570*4d495c6eSApple OSS Distributions 
1571*4d495c6eSApple OSS Distributions 	tsr_port = thread_get_special_reply_port();
1572*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(MACH_PORT_VALID(tsr_port), "get_thread_special_reply_port");
1573*4d495c6eSApple OSS Distributions 
1574*4d495c6eSApple OSS Distributions 	T_LOG("Sending to the connection port with a sync IPC");
1575*4d495c6eSApple OSS Distributions 	send(conn_port, tsr_port, MACH_PORT_NULL,
1576*4d495c6eSApple OSS Distributions 	    g_expected_qos[ENV_QOS_BEFORE_OVERRIDE],
1577*4d495c6eSApple OSS Distributions 	    MACH_SEND_PROPAGATE_QOS);
1578*4d495c6eSApple OSS Distributions 
1579*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_AFTER_OVERRIDE],
1580*4d495c6eSApple OSS Distributions 	    qos_client_send_complex_msg_to_service_port);
1581*4d495c6eSApple OSS Distributions 
1582*4d495c6eSApple OSS Distributions 	receive(tsr_port, conn_port);
1583*4d495c6eSApple OSS Distributions 
1584*4d495c6eSApple OSS Distributions 	sleep(3 * SEND_TIMEOUT_SECS);
1585*4d495c6eSApple OSS Distributions 
1586*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("client timed out");
1587*4d495c6eSApple OSS Distributions 	return NULL;
1588*4d495c6eSApple OSS Distributions }
1589*4d495c6eSApple OSS Distributions 
1590*4d495c6eSApple OSS Distributions T_HELPER_DECL(qos_client_send_complex_msg_with_pri,
1591*4d495c6eSApple OSS Distributions     "Send a message with several ports causing links")
1592*4d495c6eSApple OSS Distributions {
1593*4d495c6eSApple OSS Distributions 	thread_create_at_qos(g_expected_qos[ENV_QOS_BEFORE_OVERRIDE],
1594*4d495c6eSApple OSS Distributions 	    qos_client_send_to_connection_then_service_port);
1595*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1596*4d495c6eSApple OSS Distributions }
1597*4d495c6eSApple OSS Distributions 
1598*4d495c6eSApple OSS Distributions static void
run_client_server(const char * server_name,const char * client_name,qos_class_t qos[],const char * qos_name[],const char * wl_function)1599*4d495c6eSApple OSS Distributions run_client_server(const char *server_name, const char *client_name, qos_class_t qos[],
1600*4d495c6eSApple OSS Distributions     const char *qos_name[], const char *wl_function)
1601*4d495c6eSApple OSS Distributions {
1602*4d495c6eSApple OSS Distributions 	char *env[2 * ENV_VAR_QOS + ENV_VAR_FUNCTION + 1];
1603*4d495c6eSApple OSS Distributions 	env_set_qos(env, qos, qos_name, wl_function);
1604*4d495c6eSApple OSS Distributions 
1605*4d495c6eSApple OSS Distributions 	for (int i = 0; i < ENV_VAR_QOS; i++) {
1606*4d495c6eSApple OSS Distributions 		g_expected_qos[i] = qos[i];
1607*4d495c6eSApple OSS Distributions 		g_expected_qos_name[i] = qos_name[i];
1608*4d495c6eSApple OSS Distributions 	}
1609*4d495c6eSApple OSS Distributions 
1610*4d495c6eSApple OSS Distributions 	dt_helper_t helpers[] = {
1611*4d495c6eSApple OSS Distributions 		dt_launchd_helper_domain("com.apple.xnu.test.kevent_qos.plist",
1612*4d495c6eSApple OSS Distributions 	    server_name, env, LAUNCH_SYSTEM_DOMAIN),
1613*4d495c6eSApple OSS Distributions 		dt_fork_helper(client_name)
1614*4d495c6eSApple OSS Distributions 	};
1615*4d495c6eSApple OSS Distributions 	dt_run_helpers(helpers, 2, HELPER_TIMEOUT_SECS);
1616*4d495c6eSApple OSS Distributions }
1617*4d495c6eSApple OSS Distributions 
1618*4d495c6eSApple OSS Distributions #pragma mark Mach receive - kevent_qos
1619*4d495c6eSApple OSS Distributions 
1620*4d495c6eSApple OSS Distributions static void
expect_kevent_id_recv(mach_port_t port,qos_class_t qos[],const char * qos_name[],const char * wl_function)1621*4d495c6eSApple OSS Distributions expect_kevent_id_recv(mach_port_t port, qos_class_t qos[], const char *qos_name[], const char *wl_function)
1622*4d495c6eSApple OSS Distributions {
1623*4d495c6eSApple OSS Distributions 	int r;
1624*4d495c6eSApple OSS Distributions 
1625*4d495c6eSApple OSS Distributions 	/* Qos expected by workloop thread */
1626*4d495c6eSApple OSS Distributions 	for (int i = 0; i < ENV_VAR_QOS; i++) {
1627*4d495c6eSApple OSS Distributions 		g_expected_qos[i] = qos[i];
1628*4d495c6eSApple OSS Distributions 		g_expected_qos_name[i] = qos_name[i];
1629*4d495c6eSApple OSS Distributions 	}
1630*4d495c6eSApple OSS Distributions 
1631*4d495c6eSApple OSS Distributions 	if (strcmp(wl_function, "workloop_cb_test_intransit") == 0) {
1632*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1633*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1634*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_intransit, 0, 0), NULL);
1635*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send") == 0) {
1636*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1637*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1638*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send, 0, 0), NULL);
1639*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_and_enable") == 0) {
1640*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1641*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1642*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_and_enable, 0, 0), NULL);
1643*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_and_enable_handoff") == 0) {
1644*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1645*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1646*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_and_enable_handoff, 0, 0), NULL);
1647*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_send_two_sync") == 0) {
1648*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1649*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1650*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_send_two_sync, 0, 0), NULL);
1651*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_two_send_and_destroy") == 0) {
1652*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1653*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1654*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_two_send_and_destroy, 0, 0), NULL);
1655*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_reply") == 0) {
1656*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1657*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1658*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_reply, 0, 0), NULL);
1659*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_deallocate") == 0) {
1660*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1661*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1662*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_deallocate, 0, 0), NULL);
1663*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_reply_kevent") == 0) {
1664*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1665*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1666*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_reply_kevent, 0, 0), NULL);
1667*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_reply_kevent_pthread") == 0) {
1668*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1669*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1670*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_reply_kevent_pthread, 0, 0), NULL);
1671*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_kevent_reply") == 0) {
1672*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1673*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1674*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_kevent_reply, 0, 0), NULL);
1675*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_do_nothing") == 0) {
1676*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1677*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1678*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_do_nothing, 0, 0), NULL);
1679*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_do_nothing_kevent_pthread") == 0) {
1680*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1681*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1682*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_do_nothing_kevent_pthread, 0, 0), NULL);
1683*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_do_nothing_exit") == 0) {
1684*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1685*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1686*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_do_nothing_exit, 0, 0), NULL);
1687*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_reply_kevent_reply_kevent") == 0) {
1688*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1689*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1690*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_reply_kevent_reply_kevent, 0, 0), NULL);
1691*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_kevent_reply_reply_kevent") == 0) {
1692*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1693*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1694*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_kevent_reply_reply_kevent, 0, 0), NULL);
1695*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_kevent_reply_kevent_reply") == 0) {
1696*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1697*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1698*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_kevent_reply_kevent_reply, 0, 0), NULL);
1699*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_sync_send_reply_kevent_kevent_reply") == 0) {
1700*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1701*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1702*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_sync_send_reply_kevent_kevent_reply, 0, 0), NULL);
1703*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_kernel_sync_send") == 0) {
1704*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1705*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1706*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_kernel_sync_send, 0, 0), NULL);
1707*4d495c6eSApple OSS Distributions 	} else if (strcmp(wl_function, "workloop_cb_test_kernel_async_send") == 0) {
1708*4d495c6eSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(_pthread_workqueue_init_with_workloop(
1709*4d495c6eSApple OSS Distributions 			    worker_cb, event_cb,
1710*4d495c6eSApple OSS Distributions 			    (pthread_workqueue_function_workloop_t)workloop_cb_test_kernel_async_send, 0, 0), NULL);
1711*4d495c6eSApple OSS Distributions 	} else {
1712*4d495c6eSApple OSS Distributions 		T_ASSERT_FAIL("no workloop function specified \n");
1713*4d495c6eSApple OSS Distributions 	}
1714*4d495c6eSApple OSS Distributions 
1715*4d495c6eSApple OSS Distributions 	struct kevent_qos_s kev = {
1716*4d495c6eSApple OSS Distributions 		.ident = port,
1717*4d495c6eSApple OSS Distributions 		.filter = EVFILT_MACHPORT,
1718*4d495c6eSApple OSS Distributions 		.flags = EV_ADD | EV_UDATA_SPECIFIC | EV_DISPATCH | EV_VANISHED,
1719*4d495c6eSApple OSS Distributions 		.fflags = (MACH_RCV_MSG | MACH_RCV_VOUCHER | MACH_RCV_LARGE | MACH_RCV_LARGE_IDENTITY |
1720*4d495c6eSApple OSS Distributions 	    MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV) |
1721*4d495c6eSApple OSS Distributions 	    MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)),
1722*4d495c6eSApple OSS Distributions 		.data = 1,
1723*4d495c6eSApple OSS Distributions 		.qos = (int32_t)_pthread_qos_class_encode(qos[ENV_QOS_QUEUE_OVERRIDE], 0, 0)
1724*4d495c6eSApple OSS Distributions 	};
1725*4d495c6eSApple OSS Distributions 
1726*4d495c6eSApple OSS Distributions 	struct kevent_qos_s kev_err = { 0 };
1727*4d495c6eSApple OSS Distributions 
1728*4d495c6eSApple OSS Distributions 	/* Setup workloop for mach msg rcv */
1729*4d495c6eSApple OSS Distributions 	r = kevent_id(25, &kev, 1, &kev_err, 1, NULL,
1730*4d495c6eSApple OSS Distributions 	    NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_ERROR_EVENTS);
1731*4d495c6eSApple OSS Distributions 
1732*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(r, "kevent_id");
1733*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(r, 0, "no errors returned from kevent_id");
1734*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1735*4d495c6eSApple OSS Distributions }
1736*4d495c6eSApple OSS Distributions 
1737*4d495c6eSApple OSS Distributions T_HELPER_DECL(server_kevent_id,
1738*4d495c6eSApple OSS Distributions     "Reply with the QoS that a dispatch source event handler ran with")
1739*4d495c6eSApple OSS Distributions {
1740*4d495c6eSApple OSS Distributions 	qos_class_t qos[ENV_VAR_QOS];
1741*4d495c6eSApple OSS Distributions 	const char *qos_name[ENV_VAR_QOS];
1742*4d495c6eSApple OSS Distributions 	const char *wl_function;
1743*4d495c6eSApple OSS Distributions 	environ_get_qos(qos, qos_name, &wl_function);
1744*4d495c6eSApple OSS Distributions 
1745*4d495c6eSApple OSS Distributions 	expect_kevent_id_recv(get_server_port(), qos, qos_name, wl_function);
1746*4d495c6eSApple OSS Distributions 	sleep(HELPER_TIMEOUT_SECS);
1747*4d495c6eSApple OSS Distributions 	T_ASSERT_FAIL("should receive a message within %d seconds",
1748*4d495c6eSApple OSS Distributions 	    RECV_TIMEOUT_SECS);
1749*4d495c6eSApple OSS Distributions }
1750*4d495c6eSApple OSS Distributions 
1751*4d495c6eSApple OSS Distributions static void *
special_reply_port_thread(void * ctxt)1752*4d495c6eSApple OSS Distributions special_reply_port_thread(void *ctxt)
1753*4d495c6eSApple OSS Distributions {
1754*4d495c6eSApple OSS Distributions 	kern_return_t ret;
1755*4d495c6eSApple OSS Distributions 	mach_port_t rcv_port = *(mach_port_t *)ctxt;
1756*4d495c6eSApple OSS Distributions 	struct test_msg rcv_msg = {
1757*4d495c6eSApple OSS Distributions 		.header = {
1758*4d495c6eSApple OSS Distributions 			.msgh_remote_port = MACH_PORT_NULL,
1759*4d495c6eSApple OSS Distributions 			.msgh_local_port  = rcv_port,
1760*4d495c6eSApple OSS Distributions 			.msgh_size        = sizeof(rcv_msg),
1761*4d495c6eSApple OSS Distributions 		},
1762*4d495c6eSApple OSS Distributions 	};
1763*4d495c6eSApple OSS Distributions 
1764*4d495c6eSApple OSS Distributions 	ret = mach_msg(&rcv_msg.header, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
1765*4d495c6eSApple OSS Distributions 	    rcv_msg.header.msgh_size, rcv_port, 1000, MACH_PORT_NULL);
1766*4d495c6eSApple OSS Distributions 
1767*4d495c6eSApple OSS Distributions 	T_EXPECT_EQ(ret, MACH_RCV_TIMED_OUT, "receive should not panic");
1768*4d495c6eSApple OSS Distributions 
1769*4d495c6eSApple OSS Distributions 	*(mach_port_t *)ctxt = MACH_PORT_NULL;
1770*4d495c6eSApple OSS Distributions 
1771*4d495c6eSApple OSS Distributions 	sleep(1); // give some time to pthread_exit
1772*4d495c6eSApple OSS Distributions 
1773*4d495c6eSApple OSS Distributions 	ret = mach_msg(&rcv_msg.header, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
1774*4d495c6eSApple OSS Distributions 	    rcv_msg.header.msgh_size, rcv_port, 1000, MACH_PORT_NULL);
1775*4d495c6eSApple OSS Distributions 
1776*4d495c6eSApple OSS Distributions 	T_EXPECT_EQ(ret, MACH_RCV_TIMED_OUT, "receive should not panic");
1777*4d495c6eSApple OSS Distributions 
1778*4d495c6eSApple OSS Distributions 	T_END;
1779*4d495c6eSApple OSS Distributions }
1780*4d495c6eSApple OSS Distributions 
1781*4d495c6eSApple OSS Distributions T_DECL(special_reply_port, "basic special reply port robustness checks",
1782*4d495c6eSApple OSS Distributions     T_META_RUN_CONCURRENTLY(true), T_META_TAG_VM_PREFERRED)
1783*4d495c6eSApple OSS Distributions {
1784*4d495c6eSApple OSS Distributions 	pthread_t thread;
1785*4d495c6eSApple OSS Distributions 	mach_port_t srp = thread_get_special_reply_port();
1786*4d495c6eSApple OSS Distributions 
1787*4d495c6eSApple OSS Distributions 	pthread_create(&thread, NULL, special_reply_port_thread, &srp);
1788*4d495c6eSApple OSS Distributions 
1789*4d495c6eSApple OSS Distributions 	while (srp) {
1790*4d495c6eSApple OSS Distributions 		usleep(1000);
1791*4d495c6eSApple OSS Distributions 	}
1792*4d495c6eSApple OSS Distributions 
1793*4d495c6eSApple OSS Distributions 	pthread_exit(NULL);
1794*4d495c6eSApple OSS Distributions }
1795*4d495c6eSApple OSS Distributions 
1796*4d495c6eSApple OSS Distributions #define TEST_QOS(server_name, client_name, name, wl_function_name, qos_bo, qos_bo_name, qos_qo, qos_qo_name, qos_ao, qos_ao_name) \
1797*4d495c6eSApple OSS Distributions 	T_DECL(server_kevent_id_##name, \
1798*4d495c6eSApple OSS Distributions 	                "Event delivery at " qos_ao_name " QoS using a kevent_id", \
1799*4d495c6eSApple OSS Distributions 	                T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED) \
1800*4d495c6eSApple OSS Distributions 	{ \
1801*4d495c6eSApple OSS Distributions 	        qos_class_t qos_array[ENV_VAR_QOS] = {qos_bo, qos_qo, qos_ao};  \
1802*4d495c6eSApple OSS Distributions 	        const char *qos_name_array[ENV_VAR_QOS] = {qos_bo_name, qos_qo_name, qos_ao_name}; \
1803*4d495c6eSApple OSS Distributions 	        run_client_server(server_name, client_name, qos_array, qos_name_array, wl_function_name); \
1804*4d495c6eSApple OSS Distributions 	}
1805*4d495c6eSApple OSS Distributions /*
1806*4d495c6eSApple OSS Distributions  * Test 1: Test special reply port SPI
1807*4d495c6eSApple OSS Distributions  *
1808*4d495c6eSApple OSS Distributions  * Create thread special reply port and check any subsequent calls to
1809*4d495c6eSApple OSS Distributions  * the same should return MACH_PORT_NULL, unless the reply port is destroyed.
1810*4d495c6eSApple OSS Distributions  */
1811*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_get_special_reply_port", special_reply_port, "workloop_cb_test_intransit",
1812*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1813*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1814*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1815*4d495c6eSApple OSS Distributions 
1816*4d495c6eSApple OSS Distributions /*
1817*4d495c6eSApple OSS Distributions  * Test 2: Test sync ipc send to an in-transit port
1818*4d495c6eSApple OSS Distributions  *
1819*4d495c6eSApple OSS Distributions  * Send a sync ipc message (at IN qos) to an in-transit port enqueued in a port
1820*4d495c6eSApple OSS Distributions  * attached to a workloop. Test that the servicer of the workloop gets
1821*4d495c6eSApple OSS Distributions  * sync ipc override.
1822*4d495c6eSApple OSS Distributions  */
1823*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_to_intransit_with_thr_pri", transit_IN, "workloop_cb_test_intransit",
1824*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1825*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1826*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated")
1827*4d495c6eSApple OSS Distributions 
1828*4d495c6eSApple OSS Distributions /*
1829*4d495c6eSApple OSS Distributions  * Test 3: Test sync ipc send to an in-transit port
1830*4d495c6eSApple OSS Distributions  *
1831*4d495c6eSApple OSS Distributions  * Send a sync ipc message (at UI qos) to an in-transit port enqueued in a port
1832*4d495c6eSApple OSS Distributions  * attached to a workloop. Test that the servicer of the workloop gets
1833*4d495c6eSApple OSS Distributions  * sync ipc override.
1834*4d495c6eSApple OSS Distributions  */
1835*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_to_intransit_with_thr_pri", transit_UI, "workloop_cb_test_intransit",
1836*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated",
1837*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1838*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1839*4d495c6eSApple OSS Distributions 
1840*4d495c6eSApple OSS Distributions /*
1841*4d495c6eSApple OSS Distributions  * Test 4: Test starting a sync rcv overrides the servicer
1842*4d495c6eSApple OSS Distributions  *
1843*4d495c6eSApple OSS Distributions  * Send an async message to a port and then start waiting on
1844*4d495c6eSApple OSS Distributions  * the port in mach msg rcv (at IN qos) with sync wait and test if the
1845*4d495c6eSApple OSS Distributions  * servicer of the workloop gets sync ipc override.
1846*4d495c6eSApple OSS Distributions  */
1847*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_and_sync_rcv", rcv_IN, "workloop_cb_test_intransit",
1848*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1849*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1850*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated")
1851*4d495c6eSApple OSS Distributions 
1852*4d495c6eSApple OSS Distributions /*
1853*4d495c6eSApple OSS Distributions  * Test 5: Test starting a sync rcv overrides the servicer
1854*4d495c6eSApple OSS Distributions  *
1855*4d495c6eSApple OSS Distributions  * Send an async message to a port and then start waiting on
1856*4d495c6eSApple OSS Distributions  * the port in mach msg rcv (at UI qos) with sync wait and test if the
1857*4d495c6eSApple OSS Distributions  * servicer of the workloop gets sync ipc override.
1858*4d495c6eSApple OSS Distributions  */
1859*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_and_sync_rcv", rcv_UI, "workloop_cb_test_intransit",
1860*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1861*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1862*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user interactive with 47 basepri promotion")
1863*4d495c6eSApple OSS Distributions 
1864*4d495c6eSApple OSS Distributions /*
1865*4d495c6eSApple OSS Distributions  * Test 6: test sending sync ipc message (at IN qos) to port will override the servicer
1866*4d495c6eSApple OSS Distributions  *
1867*4d495c6eSApple OSS Distributions  * Send a message with sync ipc override to a port and check if the servicer
1868*4d495c6eSApple OSS Distributions  * of the workloop on other side gets sync ipc override.
1869*4d495c6eSApple OSS Distributions  */
1870*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_pri", send_sync_IN, "workloop_cb_test_sync_send",
1871*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1872*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1873*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated")
1874*4d495c6eSApple OSS Distributions 
1875*4d495c6eSApple OSS Distributions /*
1876*4d495c6eSApple OSS Distributions  * Test 7: test sending sync ipc message (at UI qos) to port will override the servicer
1877*4d495c6eSApple OSS Distributions  *
1878*4d495c6eSApple OSS Distributions  * Send a message with sync ipc override to a port and check if the servicer
1879*4d495c6eSApple OSS Distributions  * of the workloop on other side gets sync ipc override.
1880*4d495c6eSApple OSS Distributions  */
1881*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_pri", send_sync_UI, "workloop_cb_test_sync_send",
1882*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1883*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1884*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1885*4d495c6eSApple OSS Distributions 
1886*4d495c6eSApple OSS Distributions /*
1887*4d495c6eSApple OSS Distributions  * Test 8: test enabling a knote in workloop handler will drop the sync ipc override of delivered message
1888*4d495c6eSApple OSS Distributions  *
1889*4d495c6eSApple OSS Distributions  * Send a sync ipc message to port and check the servicer of the workloop
1890*4d495c6eSApple OSS Distributions  * on other side gets sync ipc override and once the handler enables the knote,
1891*4d495c6eSApple OSS Distributions  * that sync ipc override is dropped.
1892*4d495c6eSApple OSS Distributions  */
1893*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_pri", send_sync_UI_and_enable, "workloop_cb_test_sync_send_and_enable",
1894*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1895*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1896*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1897*4d495c6eSApple OSS Distributions 
1898*4d495c6eSApple OSS Distributions /*
1899*4d495c6eSApple OSS Distributions  * Test 9: test returning to begin processing drops sync ipc override of delivered message
1900*4d495c6eSApple OSS Distributions  *
1901*4d495c6eSApple OSS Distributions  * Send a sync ipc message and check if enabling the knote clears the override of
1902*4d495c6eSApple OSS Distributions  * the delivered message, but should still have the override of an enqueued message.
1903*4d495c6eSApple OSS Distributions  */
1904*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_two_sync_msg_with_thr_pri", send_two_sync_UI, "workloop_cb_test_send_two_sync",
1905*4d495c6eSApple OSS Distributions     QOS_CLASS_BACKGROUND, "background",
1906*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1907*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1908*4d495c6eSApple OSS Distributions 
1909*4d495c6eSApple OSS Distributions /*
1910*4d495c6eSApple OSS Distributions  * Test 10: test destroying the special reply port drops the override
1911*4d495c6eSApple OSS Distributions  *
1912*4d495c6eSApple OSS Distributions  * Send an async messages and a sync ipc message, the workloop handler
1913*4d495c6eSApple OSS Distributions  * should get a sync ipc override, now test if destroying the special
1914*4d495c6eSApple OSS Distributions  * reply port drops the sync ipc override on the servicer.
1915*4d495c6eSApple OSS Distributions  */
1916*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_two_msg_and_destroy", send_two_UI_and_destroy, "workloop_cb_test_two_send_and_destroy",
1917*4d495c6eSApple OSS Distributions     QOS_CLASS_BACKGROUND, "background",
1918*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1919*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1920*4d495c6eSApple OSS Distributions 
1921*4d495c6eSApple OSS Distributions /*
1922*4d495c6eSApple OSS Distributions  * Test 11: test sending two ports with chaining
1923*4d495c6eSApple OSS Distributions  *
1924*4d495c6eSApple OSS Distributions  * Send a sync IPC to a connection port, which itself is embedded in a message
1925*4d495c6eSApple OSS Distributions  * sent as a sync IPC to a service port.
1926*4d495c6eSApple OSS Distributions  */
1927*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_complex_msg_with_pri", send_complex_sync_UI_and_enable, "workloop_cb_test_sync_send_and_enable",
1928*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated",
1929*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated",
1930*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1931*4d495c6eSApple OSS Distributions 
1932*4d495c6eSApple OSS Distributions /*
1933*4d495c6eSApple OSS Distributions  * Test 12: test sending two ports with chaining
1934*4d495c6eSApple OSS Distributions  *
1935*4d495c6eSApple OSS Distributions  * Send a sync IPC to a connection port, which itself is embedded in a message
1936*4d495c6eSApple OSS Distributions  * sent as a sync IPC to a service port.
1937*4d495c6eSApple OSS Distributions  */
1938*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_complex_msg_with_pri", send_complex_sync_UI_and_enable_and_handoff, "workloop_cb_test_sync_send_and_enable_handoff",
1939*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated",
1940*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated",
1941*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INTERACTIVE, "user initiated with 47 basepri promotion")
1942*4d495c6eSApple OSS Distributions 
1943*4d495c6eSApple OSS Distributions /*
1944*4d495c6eSApple OSS Distributions  * Test 13: test changing qos of a thread to trigger turnstile push
1945*4d495c6eSApple OSS Distributions  *
1946*4d495c6eSApple OSS Distributions  * Send a sync IPC to a service port and change the qos of the blocked thread
1947*4d495c6eSApple OSS Distributions  * to verify that changing qos triggers a turnstile push.
1948*4d495c6eSApple OSS Distributions  */
1949*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_sync_rcv_qos_change", qos_change_to_IN, "workloop_cb_test_intransit",
1950*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1951*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
1952*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated")
1953*4d495c6eSApple OSS Distributions 
1954*4d495c6eSApple OSS Distributions /*
1955*4d495c6eSApple OSS Distributions  * Test 14 - 21
1956*4d495c6eSApple OSS Distributions  *
1957*4d495c6eSApple OSS Distributions  * Test single sync ipc link with server that breaks/preserves the link in different ways.
1958*4d495c6eSApple OSS Distributions  */
1959*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_correct_server", send_sync_link_correct_server_s, "workloop_cb_test_sync_send_reply",
1960*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1961*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1962*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1963*4d495c6eSApple OSS Distributions 
1964*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_correct_server", send_sync_link_correct_server_d, "workloop_cb_test_sync_send_deallocate",
1965*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1966*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1967*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1968*4d495c6eSApple OSS Distributions 
1969*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_correct_server", send_sync_link_correct_server_sk, "workloop_cb_test_sync_send_reply_kevent",
1970*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1971*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1972*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1973*4d495c6eSApple OSS Distributions 
1974*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_correct_server", send_sync_link_correct_server_skp, "workloop_cb_test_sync_send_reply_kevent_pthread",
1975*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1976*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1977*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1978*4d495c6eSApple OSS Distributions 
1979*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_incorrect_server", send_sync_link_incorrect_server_ks, "workloop_cb_test_sync_send_kevent_reply",
1980*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1981*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1982*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1983*4d495c6eSApple OSS Distributions 
1984*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_correct_server", send_sync_link_correct_server_n, "workloop_cb_test_sync_send_do_nothing",
1985*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1986*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1987*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1988*4d495c6eSApple OSS Distributions 
1989*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_incorrect_server", send_sync_link_incorrect_server_kp, "workloop_cb_test_sync_send_do_nothing_kevent_pthread",
1990*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1991*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1992*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1993*4d495c6eSApple OSS Distributions 
1994*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_sync_msg_with_link_check_correct_server", send_sync_link_correct_server_e, "workloop_cb_test_sync_send_do_nothing_exit",
1995*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1996*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
1997*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
1998*4d495c6eSApple OSS Distributions 
1999*4d495c6eSApple OSS Distributions /*
2000*4d495c6eSApple OSS Distributions  * Test 22 - 25
2001*4d495c6eSApple OSS Distributions  *
2002*4d495c6eSApple OSS Distributions  * Test sequential sync ipc link with server that breaks/preserves the link.
2003*4d495c6eSApple OSS Distributions  */
2004*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_2sync_msg_with_link_check_correct_server", send_2sync_link_correct_server_sksk, "workloop_cb_test_sync_send_reply_kevent_reply_kevent",
2005*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2006*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2007*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
2008*4d495c6eSApple OSS Distributions 
2009*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_2sync_msg_with_link_check_incorrect_server", send_2sync_link_incorrect_server_kssk, "workloop_cb_test_sync_send_kevent_reply_reply_kevent",
2010*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2011*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2012*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
2013*4d495c6eSApple OSS Distributions 
2014*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_2sync_msg_with_link_check_incorrect_server", send_2sync_link_incorrect_server_ksks, "workloop_cb_test_sync_send_kevent_reply_kevent_reply",
2015*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2016*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2017*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
2018*4d495c6eSApple OSS Distributions 
2019*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_2sync_msg_with_link_check_incorrect_server", send_2sync_link_incorrect_server_skks, "workloop_cb_test_sync_send_reply_kevent_kevent_reply",
2020*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2021*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default",
2022*4d495c6eSApple OSS Distributions     QOS_CLASS_DEFAULT, "default")
2023*4d495c6eSApple OSS Distributions 
2024*4d495c6eSApple OSS Distributions /*
2025*4d495c6eSApple OSS Distributions  * Test 26: test sending sync ipc from kernel (at IN qos) to port will override the servicer
2026*4d495c6eSApple OSS Distributions  *
2027*4d495c6eSApple OSS Distributions  * Do a kernel upcall at IN qos to a port and check if the servicer
2028*4d495c6eSApple OSS Distributions  * of the workloop on other side gets sync ipc override.
2029*4d495c6eSApple OSS Distributions  */
2030*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_client_send_kernel_upcall_sync_msg_with_pri", kernel_send_sync_IN, "workloop_cb_test_kernel_sync_send",
2031*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
2032*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
2033*4d495c6eSApple OSS Distributions     QOS_CLASS_USER_INITIATED, "user initiated")
2034*4d495c6eSApple OSS Distributions 
2035*4d495c6eSApple OSS Distributions /*
2036*4d495c6eSApple OSS Distributions  * Test 27: test sending async ipc from kernel (at IN qos and Tier 0 iotier) to port will override the servicer
2037*4d495c6eSApple OSS Distributions  *
2038*4d495c6eSApple OSS Distributions  * Do a kernel upcall at IN qos and Tier 0 iotier to a port and check if
2039*4d495c6eSApple OSS Distributions  * the servicer of the workloop on the other side gets the ipc override.
2040*4d495c6eSApple OSS Distributions  */
2041*4d495c6eSApple OSS Distributions TEST_QOS("server_kevent_id", "qos_iotier_client_send_kernel_upcall_async_msg", kernel_send_async_IN, "workloop_cb_test_kernel_async_send",
2042*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
2043*4d495c6eSApple OSS Distributions     QOS_CLASS_MAINTENANCE, "maintenance",
2044*4d495c6eSApple OSS Distributions     QOS_CLASS_UTILITY, "utility")
2045