@@ -207,105 +207,120 @@ pub enum QoSClass {
207
207
UserInteractive ,
208
208
}
209
209
210
- #[ cfg( target_vendor = "apple" ) ]
211
- pub const IS_QOS_AVAILABLE : bool = true ;
210
+ pub const IS_QOS_AVAILABLE : bool = imp:: IS_QOS_AVAILABLE ;
212
211
213
- #[ cfg( not( target_vendor = "apple" ) ) ]
214
- pub const IS_QOS_AVAILABLE : bool = false ;
212
+ pub fn set_current_thread_qos_class ( class : QoSClass ) {
213
+ imp:: set_current_thread_qos_class ( class)
214
+ }
215
+
216
+ pub fn get_current_thread_qos_class ( ) -> Option < QoSClass > {
217
+ imp:: get_current_thread_qos_class ( )
218
+ }
215
219
216
220
// All Apple platforms use XNU as their kernel
217
221
// and thus have the concept of QoS.
218
222
#[ cfg( target_vendor = "apple" ) ]
219
- pub fn set_current_thread_qos_class ( class : QoSClass ) {
220
- let c = match class {
221
- QoSClass :: UserInteractive => libc:: qos_class_t:: QOS_CLASS_USER_INTERACTIVE ,
222
- QoSClass :: UserInitiated => libc:: qos_class_t:: QOS_CLASS_USER_INITIATED ,
223
- QoSClass :: Utility => libc:: qos_class_t:: QOS_CLASS_UTILITY ,
224
- QoSClass :: Background => libc:: qos_class_t:: QOS_CLASS_BACKGROUND ,
225
- } ;
223
+ mod imp {
224
+ use super :: QoSClass ;
226
225
227
- let code = unsafe { libc :: pthread_set_qos_class_self_np ( c , 0 ) } ;
226
+ pub ( super ) const IS_QOS_AVAILABLE : bool = true ;
228
227
229
- if code == 0 {
230
- return ;
231
- }
228
+ pub ( super ) fn set_current_thread_qos_class ( class : QoSClass ) {
229
+ let c = match class {
230
+ QoSClass :: UserInteractive => libc:: qos_class_t:: QOS_CLASS_USER_INTERACTIVE ,
231
+ QoSClass :: UserInitiated => libc:: qos_class_t:: QOS_CLASS_USER_INITIATED ,
232
+ QoSClass :: Utility => libc:: qos_class_t:: QOS_CLASS_UTILITY ,
233
+ QoSClass :: Background => libc:: qos_class_t:: QOS_CLASS_BACKGROUND ,
234
+ } ;
232
235
233
- let errno = unsafe { * libc:: __error ( ) } ;
236
+ let code = unsafe { libc:: pthread_set_qos_class_self_np ( c , 0 ) } ;
234
237
235
- match errno {
236
- libc:: EPERM => {
237
- // This thread has been excluded from the QoS system
238
- // due to a previous call to a function such as `pthread_setschedparam`
239
- // which is incompatible with QoS.
240
- //
241
- // Panic instead of returning an error
242
- // to maintain the invariant that we only use QoS APIs.
243
- panic ! ( "tried to set QoS of thread which has opted out of QoS (os error {errno})" )
238
+ if code == 0 {
239
+ return ;
240
+ }
241
+
242
+ let errno = unsafe { * libc:: __error ( ) } ;
243
+
244
+ match errno {
245
+ libc:: EPERM => {
246
+ // This thread has been excluded from the QoS system
247
+ // due to a previous call to a function such as `pthread_setschedparam`
248
+ // which is incompatible with QoS.
249
+ //
250
+ // Panic instead of returning an error
251
+ // to maintain the invariant that we only use QoS APIs.
252
+ panic ! ( "tried to set QoS of thread which has opted out of QoS (os error {errno})" )
253
+ }
254
+
255
+ libc:: EINVAL => {
256
+ // This is returned if we pass something other than a qos_class_t
257
+ // to `pthread_set_qos_class_self_np`.
258
+ //
259
+ // This is impossible, so again panic.
260
+ unreachable ! (
261
+ "invalid qos_class_t value was passed to pthread_set_qos_class_self_np"
262
+ )
263
+ }
264
+
265
+ _ => {
266
+ // `pthread_set_qos_class_self_np`’s documentation
267
+ // does not mention any other errors.
268
+ unreachable ! ( "`pthread_set_qos_class_self_np` returned unexpected error {errno}" )
269
+ }
244
270
}
271
+ }
245
272
246
- libc:: EINVAL => {
247
- // This is returned if we pass something other than a qos_class_t
248
- // to `pthread_set_qos_class_self_np`.
273
+ pub ( super ) fn get_current_thread_qos_class ( ) -> Option < QoSClass > {
274
+ let current_thread = unsafe { libc:: pthread_self ( ) } ;
275
+ let mut qos_class_raw = libc:: qos_class_t:: QOS_CLASS_UNSPECIFIED ;
276
+ let code = unsafe {
277
+ libc:: pthread_get_qos_class_np ( current_thread, & mut qos_class_raw, std:: ptr:: null_mut ( ) )
278
+ } ;
279
+
280
+ if code != 0 {
281
+ // `pthread_get_qos_class_np`’s documentation states that
282
+ // an error value is placed into errno if the return code is not zero.
283
+ // However, it never states what errors are possible.
284
+ // Inspecting the source[0] shows that, as of this writing, it always returns zero.
285
+ //
286
+ // Whatever errors the function could report in future are likely to be
287
+ // ones which we cannot handle anyway
249
288
//
250
- // This is impossible, so again panic.
251
- unreachable ! ( "invalid qos_class_t value was passed to pthread_set_qos_class_self_np" )
289
+ // 0: https://github.com/apple-oss-distributions/libpthread/blob/67e155c94093be9a204b69637d198eceff2c7c46/src/qos.c#L171-L177
290
+ let errno = unsafe { * libc:: __error ( ) } ;
291
+ unreachable ! ( "`pthread_get_qos_class_np` failed unexpectedly (os error {errno})" ) ;
252
292
}
253
293
254
- _ => {
255
- // `pthread_set_qos_class_self_np`’s documentation
256
- // does not mention any other errors.
257
- unreachable ! ( "`pthread_set_qos_class_self_np` returned unexpected error {errno}" )
294
+ match qos_class_raw {
295
+ libc:: qos_class_t:: QOS_CLASS_USER_INTERACTIVE => Some ( QoSClass :: UserInteractive ) ,
296
+ libc:: qos_class_t:: QOS_CLASS_USER_INITIATED => Some ( QoSClass :: UserInitiated ) ,
297
+ libc:: qos_class_t:: QOS_CLASS_DEFAULT => None , // QoS has never been set
298
+ libc:: qos_class_t:: QOS_CLASS_UTILITY => Some ( QoSClass :: Utility ) ,
299
+ libc:: qos_class_t:: QOS_CLASS_BACKGROUND => Some ( QoSClass :: Background ) ,
300
+
301
+ libc:: qos_class_t:: QOS_CLASS_UNSPECIFIED => {
302
+ // Using manual scheduling APIs causes threads to “opt out” of QoS.
303
+ // At this point they become incompatible with QoS,
304
+ // and as such have the “unspecified” QoS class.
305
+ //
306
+ // Panic instead of returning an error
307
+ // to maintain the invariant that we only use QoS APIs.
308
+ panic ! ( "tried to get QoS of thread which has opted out of QoS" )
309
+ }
258
310
}
259
311
}
260
312
}
261
313
314
+ // FIXME: Windows has QoS APIs, we should use them!
262
315
#[ cfg( not( target_vendor = "apple" ) ) ]
263
- pub fn set_current_thread_qos_class ( class : QoSClass ) {
264
- // FIXME: Windows has QoS APIs, we should use them!
265
- }
316
+ mod imp {
317
+ use super :: QoSClass ;
266
318
267
- #[ cfg( target_vendor = "apple" ) ]
268
- pub fn get_current_thread_qos_class ( ) -> Option < QoSClass > {
269
- let current_thread = unsafe { libc:: pthread_self ( ) } ;
270
- let mut qos_class_raw = libc:: qos_class_t:: QOS_CLASS_UNSPECIFIED ;
271
- let code = unsafe {
272
- libc:: pthread_get_qos_class_np ( current_thread, & mut qos_class_raw, std:: ptr:: null_mut ( ) )
273
- } ;
274
-
275
- if code != 0 {
276
- // `pthread_get_qos_class_np`’s documentation states that
277
- // an error value is placed into errno if the return code is not zero.
278
- // However, it never states what errors are possible.
279
- // Inspecting the source[0] shows that, as of this writing, it always returns zero.
280
- //
281
- // Whatever errors the function could report in future are likely to be
282
- // ones which we cannot handle anyway
283
- //
284
- // 0: https://github.com/apple-oss-distributions/libpthread/blob/67e155c94093be9a204b69637d198eceff2c7c46/src/qos.c#L171-L177
285
- let errno = unsafe { * libc:: __error ( ) } ;
286
- unreachable ! ( "`pthread_get_qos_class_np` failed unexpectedly (os error {errno})" ) ;
287
- }
319
+ pub ( super ) const IS_QOS_AVAILABLE : bool = false ;
288
320
289
- match qos_class_raw {
290
- libc:: qos_class_t:: QOS_CLASS_USER_INTERACTIVE => Some ( QoSClass :: UserInteractive ) ,
291
- libc:: qos_class_t:: QOS_CLASS_USER_INITIATED => Some ( QoSClass :: UserInitiated ) ,
292
- libc:: qos_class_t:: QOS_CLASS_DEFAULT => None , // QoS has never been set
293
- libc:: qos_class_t:: QOS_CLASS_UTILITY => Some ( QoSClass :: Utility ) ,
294
- libc:: qos_class_t:: QOS_CLASS_BACKGROUND => Some ( QoSClass :: Background ) ,
295
-
296
- libc:: qos_class_t:: QOS_CLASS_UNSPECIFIED => {
297
- // Using manual scheduling APIs causes threads to “opt out” of QoS.
298
- // At this point they become incompatible with QoS,
299
- // and as such have the “unspecified” QoS class.
300
- //
301
- // Panic instead of returning an error
302
- // to maintain the invariant that we only use QoS APIs.
303
- panic ! ( "tried to get QoS of thread which has opted out of QoS" )
304
- }
305
- }
306
- }
321
+ pub ( super ) fn set_current_thread_qos_class ( _: QoSClass ) { }
307
322
308
- # [ cfg ( not ( target_vendor = "apple" ) ) ]
309
- pub fn get_current_thread_qos_class ( ) -> Option < QoSClass > {
310
- None
323
+ pub ( super ) fn get_current_thread_qos_class ( ) -> Option < QoSClass > {
324
+ None
325
+ }
311
326
}
0 commit comments