Is it possible to introspect QoS overrides via a debugger?

I was wondering if there is a way, while debugging, to observe the 'QoS boosting' behavior that is implemented in various places to provide priority inversion avoidance. The pthread_override_qos_class_start/end_np header comments specifically say that overrides aren't reflected in the qos_class_self() and pthread_get_qos_class_np() return values. As far as I can tell the 'CPU Report' UI in Xcode also does not reflect this information (perhaps for the reason the header comments call out).

Is there a direct mechanism to observe this behavior? Presumably a heuristic empirical test could be done to compare throughput of a queue that should have its priority boosted and one that should not, but I would prefer a less opaque means of verification if possible. Thanks in advance!

Accepted Reply

I don’t think there’s any any way to inspect this in the debugger. Priority boosting is done within the kernel, so there’s no ‘paper trail’ for it in user space.

You might be able to see the current state programmatically. Specifically, it might be reflected in the results returned by thread_info with the THREAD_EXTENDED_INFO selector. I don’t have time to try that out today.

However, my general advice is that you use tools to explore this stuff. My go-to tool is System Trace template in Instruments, which includes the Thread State Trace instrument. The blurb for that says:

Traces each time the OS scheduler makes a decision that could impact your application’s threads.

which is pretty awesome!

Share and Enjoy

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

Replies

I don’t think there’s any any way to inspect this in the debugger. Priority boosting is done within the kernel, so there’s no ‘paper trail’ for it in user space.

You might be able to see the current state programmatically. Specifically, it might be reflected in the results returned by thread_info with the THREAD_EXTENDED_INFO selector. I don’t have time to try that out today.

However, my general advice is that you use tools to explore this stuff. My go-to tool is System Trace template in Instruments, which includes the Thread State Trace instrument. The blurb for that says:

Traces each time the OS scheduler makes a decision that could impact your application’s threads.

which is pretty awesome!

Share and Enjoy

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

Oh, hey, you might also find the taskinfo tool useful. See for the taskinfo man page for more.

Share and Enjoy

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

Quinn, thank you (as usual) for the extremely useful suggestions! taskinfo in particular very clearly provided evidence of the expected behavior. By setting a breakpoint on a utility-qos queue right before and after enqueuing a user-initiated-qos block, I could see both the req workloop servicer override and eff thread qos move from THREAD_QOS_UTILITY to THREAD_QOS_USER_INITIATED immediately after submitting the higher-priority block (using sudo taskinfo --threads <pid>). The System Trace Instrument template also looks promising, though it surfaces so much information I was unable to clearly identify the QoS changes (no doubt I just need to research how the tool works a bit more). The thread_info approach also seems intriguing, though I haven't quite figured out what the right form of invocation is to produce that data.

For posterity, I also was pointed in the direction of the spindump tool, which also yields some insight into the QoS boosting/propagation behavior. In particular running spindump -timeline <pid> and then running my test code produced output for the relevant thread like: thread QoS user interactive (requested utility, promote user interactive, workloop servicer override utility).