macOS: what is the correct process priority?

Hello,

I am collecting process performance metrics for an application. One of those metrics is the process' priority. I am confused by the fact that there seem to be two different priorities in the kernel: the BSD process priority (sysctl API) and the Mach task priority (proc_taskinfo API).

Since I get two entirely different results for each one of them, I'd like to kindly ask for help understanding the relationship (if any) between them.

On a related note: I have tried changing the nice value for a running process and it never seems to alter the priority (regardless of whether it is the BSD or the Mach priority). Is the nice value not used on XNU?

Thanks a lot in advance for any hints! :-)

Replies

I am confused by the fact that there seem to be two different priorities in the kernel: the BSD process priority (sysctl API) and the Mach task priority (proc_taskinfo API).

I hate to add to your confusion but the latter is not a Mach API. Rather, it’s from libproc, which is not a BSD API but has more of a BSD flavour to it.

The Mach APIs are in the usr/include/mach area of the SDK, and you want to look at host_info, task_info, and thread_info. Each of these takes a ‘flavour’ parameter that describes the specific info you’re looking for. What I generally do here is:

  1. Look up the docs for the specific API.

  2. Discover one of the flavour values from that.

  3. Find that in the headers.

  4. And then look for other interesting flavours nearby.

For example, you can find the docs for task_info here, which lists the TASK_BASIC_INFO flavour, which is declared in <mach/task_info.h>, which leads to other fun flavours like TASK_EVENTS_INFO.


Taking a step back, be very careful with Mach APIs. They are supported, but only just. If there is a higher level equivalent, use that. So, for example, prefer Swift concurrency over NSThread over pthreads over Mach threads.

Your high-level goal seems to be analytics, and that’s one place where it’s pretty reasonable to use Mach APIs. It’d be best if you disabled those on production releases to limit your binary compatibility exposure, but I can understand why you might not want to do that.

One thing to avoid is basing runtime decisions on values returned by Mach APIs. I regularly see folks try to do this, and it generally doesn’t end well. For a specific example, see On Free Memory.

Oh, and this general queasiness about Mach APIs is one of the reasons that we don’t publish docs for them in the standard doc library. The only place we publish docs is in the kernel source code, starting here.

Oh, and I have at least two book recommendations for you:

  • Programming Under Mach by Boykin et al

  • Mac OS X Internals: A Systems Approach by Singh

Both are super old but they’ll give you some historical background on how this stuff fits together.

Share and Enjoy

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

Thanks a lot for your reply and especially for the book suggestions! :-)

I don't think that I can use the Mach API directly, because obtaining the Mach task_t from a PID requires special entitlements that I cannot afford to assume in my case.

Do you know whether there is a relationship between the task priority from proc_taskinfo and the process priority from sysctl?

Oh, you want to do this for some other process. That makes things trickier.

Most debugging tools actually launch the process until test, and it’s more feasible to get the task_t in that case. Another option is to add a debugging nub to the process under test that explicitly passes its task_t to your tool. You are, however, correct that this substantially increases the complexity of the whole job.

Do you know whether there is a relationship between the task priority from proc_taskinfo and the process priority from sysctl?

Not off the top of my head. When I need answers like that I usually end up rummaging around in the kernel source. That can lead you on insecure ground from a bincompat standpoint, but that’s part of the ‘joy’ of building a debugging tool.

Share and Enjoy

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