@@ -207,105 +207,120 @@ pub enum QoSClass {
207207 UserInteractive ,
208208}
209209
210- #[ cfg( target_vendor = "apple" ) ]
211- pub const IS_QOS_AVAILABLE : bool = true ;
210+ pub const IS_QOS_AVAILABLE : bool = imp:: IS_QOS_AVAILABLE ;
212211
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+ }
215219
216220// All Apple platforms use XNU as their kernel
217221// and thus have the concept of QoS.
218222#[ 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 ;
226225
227- let code = unsafe { libc :: pthread_set_qos_class_self_np ( c , 0 ) } ;
226+ pub ( super ) const IS_QOS_AVAILABLE : bool = true ;
228227
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+ } ;
232235
233- let errno = unsafe { * libc:: __error ( ) } ;
236+ let code = unsafe { libc:: pthread_set_qos_class_self_np ( c , 0 ) } ;
234237
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+ }
244270 }
271+ }
245272
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
249288 //
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})" ) ;
252292 }
253293
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+ }
258310 }
259311 }
260312}
261313
314+ // FIXME: Windows has QoS APIs, we should use them!
262315#[ 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 ;
266318
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 ;
288320
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 ) { }
307322
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+ }
311326}
0 commit comments