Setting up mach thread stack

When using create_thread_running to create a mach thread, you manually set the new thread's initial register state - including the stack pointer.


Is it safe to use any vm_allocate'd memory block for the thread's stack? I'm assuming there at least must be allignment requirments.

Accepted Reply

That being said... now that I've gone down the rabbit hole a little bit - I'm interested in how one would do it!

Well, as long as we’re talking about having fun down the rabbit hole rather than writing real code…

The answer here is surprisingly simple: you allocate (typically

mach_vm_allocate
but I don’t think there’s any API requirement for that) space for the stack and set up the registers to point to it.

I'm assuming there at least must be allignment requirments.

Right, and those are architecture specific, which isn’t a huge surprise because the whole API is architecture specific. IIRC most architectures require 16-byte alignment but, *shrug*, I haven’t done this in a while.

The bigger concern here is the lack of a pthread to wrap around your Mach thread. If your code calls any frameworks that assume a pthread—which is basically all frameworks—things will end badly. There are (even more hackish and unsupported) ways to fix this but I’ve not looked at them in detail.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Why are you creating threads using Mach rather than pthreads?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Well if pthreads are built using Mach threads, might as well just use Mach threads.


Though, after tinkering with Mach threads, I'll probably use pthreads in production - just for safety - since Mach threads arrn't documented well.


That being said, if support is there for Mach, then might aswell just use Mach.

Except the Mach interfaces are not "supported". Apple states that they are not supported public API, they are SPI. As such, they are subject to non-binary-compatible changes. The proper low-level API to use for thread is the pthread API.

Do you have a source where Apple states this isn't part of the public API? For example, vm_allocate, mach_absolute_time, thread_policy_set are part of Mach, but used ubiquitously.

It's something that Apple folks have said repeatedly in different forums and lists. One official place is: https://developer.apple.com/library/mac/technotes/tn2083/_index.html#//apple_ref/doc/uid/DTS10003794-CH1-SUBSECTION31

Recommending to not use is not the same as not supporting.


Apple discourages lots of things (even pthreads) in favour of stuff like GCD & other high-level wrappers.


But this is only because the platform is meant to be very freindly to approach even for hobbyests.

OK, let’s see if we can untangle this.

Ken wrote:

Except the Mach interfaces are not "supported".

Mach APIs are supported, in the sense that:

  • they’re in the headers in the public SDK

  • App Review won’t reject you for using them

  • DTS will answer questions about them

With regards the last point, most of the time DTS’s answer will be “use some higher-level API” but, if what you’re doing can only be accomplished using Mach APIs, we can take things from there.

As such, they are subject to non-binary-compatible changes.

Ultimately all APIs can be subject to “non-binary-compatible changes”, depending on the context (ask any Carbon developer )-: The point here is that, due to their low-level nature, and the fact that most apps use higher-level APIs, Mach APIs are more susceptible to that than other APIs.

zacho wrote:

For example,

vm_allocate
,
mach_absolute_time
,
thread_policy_set
are part of Mach, but used ubiquitously.

This is an interesting spread. Let’s take each in turn:

  • vm_allocate
    — Lots of folks use this to get page-aligned memory. Personally I’d rather use
    valloc
    or
    posix_memalign
    . Beyond that, I’d need to know the details of why you’re using
    vm_allocate
    to know whether there’s a better option.
  • mach_absolute_time
    — This is still the lowest overhead API for taking timestamps, although the performance of
    gettimeofday
    is so good these days that it’s rare that you need it. Also in 10.12 we’re adding new clock APIs (see
    <time.h>
    ) and those are both low overhead and offer features that Mach absolute time lacks.
  • thread_policy_set
    — Again, this is an interesting case. Virtually all code should be using QoS via higher-level APIs. The only exception I can think of is code with strict real-time goals, which needs
    THREAD_TIME_CONSTRAINT_POLICY
    .

Well if pthreads are built using Mach threads, might as well just use Mach threads.

That’s definitely the wrong approach to take with Mach APIs. You should use high-level APIs unless there’s a really good reason to use the Mach ones.

In the specific case of threads, pthreads brings a lot to the picture, including:

  • CPU architecture independence

  • consistency for higher-level code (lots of high-level frameworks assume that the calling thread is known to pthreads, which isn’t the case if you start it directly from Mach).

IMO starting a Mach thread directly is crazy talk! (-:

Finally, if you’re tinkering around with low-level aspects of the system I have two suggestions for you:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

@eskimo


Thank you for response!


Mach APIs are supported, in the sense that:

  • they’re in the headers in the public SDK
  • App Review won’t reject you for using them
  • DTS will answer questions about them

Precisily. Thank you for clarifying.

This is an interesting spread.

Ya - I tried to be diverse, to illustrate my point 🙂. Currently I actually only use the first 2 in production - the 3rd is something I'm currently investigating for use in a game engine.

IMO starting a Mach thread directly is crazy talk! (-:


Probably! There's a little too much architecture-specific stuff going on there, which worries me. Need to be aware of my limits.


That being said... now that I've gone down the rabbit hole a little bit - I'm interested in how one would do it! I've read a little bit of the XNU open source (http://opensource.apple.com/source/xnu/xnu-3248.60.10/) - but I guess I'll just go see how pthreads do it!

Thanks,

Zach

That being said... now that I've gone down the rabbit hole a little bit - I'm interested in how one would do it!

Well, as long as we’re talking about having fun down the rabbit hole rather than writing real code…

The answer here is surprisingly simple: you allocate (typically

mach_vm_allocate
but I don’t think there’s any API requirement for that) space for the stack and set up the registers to point to it.

I'm assuming there at least must be allignment requirments.

Right, and those are architecture specific, which isn’t a huge surprise because the whole API is architecture specific. IIRC most architectures require 16-byte alignment but, *shrug*, I haven’t done this in a while.

The bigger concern here is the lack of a pthread to wrap around your Mach thread. If your code calls any frameworks that assume a pthread—which is basically all frameworks—things will end badly. There are (even more hackish and unsupported) ways to fix this but I’ve not looked at them in detail.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you again, as always 🙂