Thread QOS class

I see this warning when my app runs:

Thread running at QOS_CLASS_USER_INTERACTIVE waiting on a lower QoS thread running at QOS_CLASS_DEFAULT. Investigate ways to avoid priority inversions

This is true; I know what is going on. I'd like this other thread to have a higher priority. But how do I set the "QOS class" for a thread?

Searching developer.apple.com for QOS_CLASS_USER_INTERACTIVE doesn't find much. It seems that dispatch queues have priorities, but in this case I have a thread, not a dispatch queue.

Any ideas?

Accepted Reply

Can I use the NSThread setThreadPriority class method for a thread that was not created using NSThread?

I wouldn’t do that. However, pthread_set_qos_class_self_np should be fine [1].

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The only way that wouldn’t work is if std::thread were spinning up Mach threads directly, which seems unlikely.

Replies

But how do I set the "QOS class" for a thread?

How did you create that thread? If, for example, you used NSThread, you can set the qualityOfService property.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How did you create that thread? If, for example, you used NSThread, you can set the qualityOfService property.

Ah-ha, thanks. Actually I am probably using a std::thread in most cases. Can I use the NSThread setThreadPriority class method for a thread that was not created using NSThread?

Can I use the NSThread setThreadPriority class method for a thread that was not created using NSThread?

In a quick test, I still see the warning after using [NSThread setThreadPriority:]. So maybe it must be an NSThread.

Can I use the NSThread setThreadPriority class method for a thread that was not created using NSThread?

I wouldn’t do that. However, pthread_set_qos_class_self_np should be fine [1].

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The only way that wouldn’t work is if std::thread were spinning up Mach threads directly, which seems unlikely.

pthread_set_qos_class_self_np

Thanks Quinn! That seems to be working.

This stuff was surprisingly difficult to find out about. The developer.apple.com search can't find anything for pthread_set_qos_class_self_np even if I know the name of the function. DuckDuckGo found this page: https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html which is quite useful, but it's in the "documentation archive" (i.e. documents that look like they were written by intelligent humans, not just scraped from headers by a bot) and I think is therefore excluded from search. But that suffers from the usual problem of telling you everything except the name of the header that you need to include. Sigh.

This stuff was surprisingly difficult to find out about.

Stuff at this level is only documented in man pages. See Reading UNIX Manual Pages for more on that. Sadly, the man pages are not on the Developer website [1].

Having said that, there isn’t a man page for pthread_set_qos_class_self_np. That is definitely bugworthy. Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Don’t ask me why or I’ll start to whimper (r. 16512537).

Stuff at this level is only documented in man pages

The first thing I did after reading your post was man pthread_set_qos_class_self_np

there isn’t a man page for pthread_set_qos_class_self_np

FB12702048

Does that mean that it's an undocumented function that I shouldn't be using? (Serious question. Recall libcache on iOS and see FB5480758.)

FB12702048

Thanks for that.

Does that mean that it's an undocumented function that I shouldn't be using?

No. My general guidelines for this sort of thing is that, barring any other info to the contrary [1], you’re allowed to use stuff that’s in the SDK headers.

Situations like this are one of the reasons I no longer use the phrase “undocumented API”.

Serious question. Recall libcache on iOS and see FB5480758.

That leads to a bug (r. 8513040) which leads to an iteration 1 DevForums URL:

https://devforums.apple.com/message/307500#307500

Sadly, that’s as far as I can follow the issue [2]. I think I know the thread you’re talking about, but I only have my half of the conversation so I’m not 100% sure.

Regardless, I don’t see any obstacle to using libcache in an iOS app:

  • The header, <cache.h>, is in the iOS SDK.

  • The routines are all decorated with availability macros that indicate it’s available starting with iOS 4.0.

  • It’s even documentated, albeit in man pages.

Every now and again I see folks get a bee in their bonnet about man pages, claiming that APIs that are only documented in man pages are macOS only. This is nonsense. By that reasoning, iOS apps wouldn’t be allowed to call printf! [3]

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The most egregious example of something that was in the SDK but wasn’t OK to use was the MAC framework. See QA1574 Kernel’s MAC framework. We’ve fixed that, finally!, but it did cause me to write QA1575 Supported KPIs.

[2] See here.

[3] Weirdly, printf is documented in the main docs, but only the Kernel framework version of it. That claims the function is only available on macOS, which is, again, nonsense. I coulda sworn I’d filed a bug about that, but I can’t seem to find the number )-: