1 /* test that the header doesn't implicitly depend on others */
2 #include <sys/work_interval.h>
12 #include <mach/mach.h>
14 #include <darwintest.h>
16 T_GLOBAL_META(T_META_NAMESPACE("xnu.scheduler"),
17 T_META_RUN_CONCURRENTLY(true));
19 static mach_port_t port
= MACH_PORT_NULL
;
21 static mach_timebase_info_data_t timebase_info
;
24 nanos_to_abs(uint64_t nanos
)
26 mach_timebase_info(&timebase_info
);
27 return nanos
* timebase_info
.denom
/ timebase_info
.numer
;
31 set_realtime(pthread_t thread
)
34 thread_time_constraint_policy_data_t pol
;
36 mach_port_t target_thread
= pthread_mach_thread_np(thread
);
37 T_EXPECT_NE(target_thread
, MACH_PORT_NULL
, "pthread_mach_thread_np");
40 pol
.period
= (uint32_t)nanos_to_abs(1000000000);
41 pol
.constraint
= (uint32_t)nanos_to_abs(100000000);
42 pol
.computation
= (uint32_t)nanos_to_abs(10000000);
44 pol
.preemptible
= 0; /* Ignored by OS */
45 kr
= thread_policy_set(target_thread
, THREAD_TIME_CONSTRAINT_POLICY
, (thread_policy_t
) &pol
,
46 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
47 T_ASSERT_MACH_SUCCESS(kr
, "thread_policy_set(THREAD_TIME_CONSTRAINT_POLICY)");
51 set_nonrealtime(pthread_t thread
)
54 thread_standard_policy_data_t pol
= {0};
56 mach_port_t target_thread
= pthread_mach_thread_np(thread
);
57 T_EXPECT_NE(target_thread
, MACH_PORT_NULL
, "pthread_mach_thread_np");
59 kr
= thread_policy_set(target_thread
, THREAD_STANDARD_POLICY
, (thread_policy_t
) &pol
,
60 THREAD_STANDARD_POLICY_COUNT
);
61 T_ASSERT_MACH_SUCCESS(kr
, "thread_policy_set(THREAD_STANDARD_POLICY)");
64 T_DECL(unentitled_work_intervals
, "work interval interface for unentitled types")
67 work_interval_t handle
= NULL
;
68 uint64_t now
= mach_absolute_time();
69 kern_return_t kr
= KERN_SUCCESS
;
71 ret
= work_interval_create(NULL
, 0);
72 T_ASSERT_EQ(errno
, EINVAL
, "create with null errno EINVAL");
73 T_ASSERT_EQ(ret
, -1, "create with null returns -1");
75 ret
= work_interval_create(&handle
, WORK_INTERVAL_FLAG_GROUP
| WORK_INTERVAL_FLAG_UNRESTRICTED
| WORK_INTERVAL_TYPE_DEFAULT
);
76 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_create, public flags");
78 ret
= work_interval_copy_port(handle
, &port
);
79 T_ASSERT_EQ(errno
, EINVAL
, "work_interval_copy_port on non-joinable interval errno EINVAL");
80 T_ASSERT_EQ(ret
, -1, "work_interval_copy_port on non-joinable interval returns -1");
82 ret
= work_interval_notify(handle
, now
- 1000, now
, now
+ 1000, now
+ 2000, 0);
83 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_notify, no flags");
85 ret
= work_interval_destroy(handle
);
86 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_destroy, no flags");
89 WORK_INTERVAL_FLAG_JOINABLE
| WORK_INTERVAL_FLAG_GROUP
| WORK_INTERVAL_FLAG_UNRESTRICTED
| WORK_INTERVAL_TYPE_DEFAULT
,
92 for (uint32_t i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
93 ret
= work_interval_create(&handle
, flags
[i
]);
94 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_create, joinable");
96 ret
= work_interval_copy_port(handle
, &port
);
97 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_copy_port, joinable");
99 ret
= work_interval_notify(handle
, now
- 1000, now
, now
+ 1000, now
+ 2000, 0);
100 T_ASSERT_EQ(ret
, -1, "work_interval_notify on non-joined thread returns -1");
101 T_ASSERT_EQ(errno
, EINVAL
, "work_interval_copy_port on non-joined thread errno EINVAL");
103 ret
= work_interval_join_port(port
);
104 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_join_port, joinable");
106 ret
= work_interval_notify(handle
, now
- 1000, now
, now
+ 1000, now
+ 2000, 0);
107 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_notify, on joined thread");
109 ret
= work_interval_join_port(port
);
110 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_join_port, join the same interval after destroy");
112 kr
= mach_port_deallocate(mach_task_self(), port
);
113 T_ASSERT_MACH_SUCCESS(kr
, "mach_port_deallocate of port");
115 ret
= work_interval_notify(handle
, now
- 1000, now
, now
+ 1000, now
+ 2000, 0);
116 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_notify, on joined thread after destroy");
118 ret
= work_interval_destroy(handle
);
119 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_destroy, joinable, on joined thread");
121 ret
= work_interval_leave();
122 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_leave, on destroyed work interval");
126 T_DECL(unentitled_work_interval_create_while_joined
, "work interval interface: create while joined")
129 work_interval_t handle
= NULL
;
130 work_interval_t handle2
= NULL
;
131 mach_port_t port1
= MACH_PORT_NULL
;
132 mach_port_t port2
= MACH_PORT_NULL
;
133 kern_return_t kr
= KERN_SUCCESS
;
135 uint32_t flags
= WORK_INTERVAL_FLAG_JOINABLE
| WORK_INTERVAL_FLAG_GROUP
| WORK_INTERVAL_FLAG_UNRESTRICTED
| WORK_INTERVAL_TYPE_DEFAULT
;
137 ret
= work_interval_create(&handle
, flags
);
138 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_create, joinable");
140 ret
= work_interval_copy_port(handle
, &port1
);
141 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_copy_port, joinable");
143 ret
= work_interval_join_port(port1
);
144 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_join_port, joinable");
147 ret
= work_interval_create(&handle2
, flags
);
148 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_create, joinable, while already joined");
150 ret
= work_interval_copy_port(handle2
, &port2
);
151 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_copy_port, joinable, while already joined");
153 ret
= work_interval_join_port(port2
);
154 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_join_port, joinable, while already joined");
156 ret
= work_interval_leave();
157 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_leave, first time");
159 ret
= work_interval_leave();
160 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_leave, again");
162 ret
= work_interval_destroy(handle
);
163 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_destroy");
165 ret
= work_interval_destroy(handle2
);
166 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_destroy");
168 kr
= mach_port_deallocate(mach_task_self(), port1
);
169 T_ASSERT_MACH_SUCCESS(kr
, "mach_port_deallocate of port");
171 kr
= mach_port_deallocate(mach_task_self(), port2
);
172 T_ASSERT_MACH_SUCCESS(kr
, "mach_port_deallocate of port");
175 T_DECL(work_interval_audio_unentitled
, "unentitled work interval for audio")
178 work_interval_t handle
= NULL
;
179 kern_return_t kr
= KERN_SUCCESS
;
181 uint32_t flags
= WORK_INTERVAL_FLAG_GROUP
| WORK_INTERVAL_FLAG_JOINABLE
| WORK_INTERVAL_TYPE_COREAUDIO
| WORK_INTERVAL_FLAG_UNRESTRICTED
;
183 ret
= work_interval_create(&handle
, flags
);
184 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_create, joinable");
186 ret
= work_interval_copy_port(handle
, &port
);
187 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_copy_port, joinable");
189 ret
= work_interval_join_port(port
);
190 T_EXPECT_POSIX_FAILURE(ret
, EINVAL
, "work_interval_join_port for audio on non-RT thread");
192 set_realtime(pthread_self());
194 ret
= work_interval_join_port(port
);
195 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_join_port for audio on RT thread");
197 ret
= work_interval_leave();
198 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_leave");
200 ret
= work_interval_destroy(handle
);
201 T_ASSERT_POSIX_SUCCESS(ret
, "work_interval_destroy");
203 kr
= mach_port_deallocate(mach_task_self(), port
);
204 T_ASSERT_MACH_SUCCESS(kr
, "mach_port_deallocate of port");
206 set_nonrealtime(pthread_self());