My Authors
Read all threads
This is a question that was asked soooo many times, and is actually the _wrong_ question to ask, so let's make a thread:

propagating QoS and priorities, what does that mean (1/...)
QoS is a label, its rules of propagation are semi complex, but DO NOT depend on the state of the system.

It's propagated by only 2 mechanisms (and anything built atop of it), and one secondary obsolete subsystem.
mechanism 1: dispatch_async
mechanism 2: XPC based IPC

the obsolete mechanism is manual pthread overrides, I will (almost) not cover them.

the propagation rules are somwhat complex (hi @jondrummond) but are a strict function of :
- the current QoS of the initiator thread,
- how you formed your dispatch_block() if using dispatch_block_create()
- the various QoS and labels of the queue you async/IPC to.
These are used to inform the scheduler following various levels of policies what priority your work item should run at.

</ the end for QoS>
Now if you _never_ wait on items synchronously that would be the end of the story, but sometimes you do, and now you enter a different world: scheduler priorities.

QoS will feed into the very complex scheme that gives you a priority but is only one aspect.
When waiting on some work, if your current priority is higher than the one of the thread running (or about to run) the work you wait on, this is called a "priority inversion".

macOS/iOS is a complex layer of tons of different priorities, leaving to chance is a bad idea.
so the OS provides measures called "priority inversion avoidance" built into a families of synchornization primitives. The way it works can be really summed up in a single sentence: when you block waiting, if the OS can know who you're blocked by, it may resolve inversions.
if it can't know, then it can't know who to apply your priority Mojo to and well, the only option is wait and hope for the best.

So what you need for priority inversion to kick in, is a wait primitive that has ownership information, IO primitives that record ownership
The list is pretty short:
- pthread mutexes and os unfair locks (and things built on top)
- dispatch_sync() (but for reasons not onto the main queue, but that doesn't matter for apps)
- xpc_connection_send_with_message_sync() (with several caveats that don't fit on Twitter)
and that's it.

now back to the original question:
- a semaphore is not an "async" operation, so QoS is _not_ related to it. in any way.
- when you call *_semaphore_wait() the OS has no idea who will call the matching *_semaphore_signal() and hence has no ownership info.
a group is essentially a semaphore with a different counting scheme: if you enter() you don't know who will leave().

that ends with the answer to the question you meant to ask "does groups have priority inversion avoidance" and the answer is "no because it has no ownership"
lastly, dispatch_block_wait() for historical reasons was implemented on top of QoS override (the now obsolete 3rd mechanism I mentionned).

Unlike priority inversion avoidance that works through multi-hop chains through _very_ cool technology (look for turnstiles in XNU)...
dispatch_block_wait() isn't multi-hop. It works for the main thread to wait in certain circumstances (if what you wait on has been asynced _before_ you start to wait on is an important one), because in an app it's the highest priority you can have,....
... so the likelyhood of requiring more than 1 hop to resolve an inversion is super low. It doesn't work nearly as well in other cases, for which a better pattern is to share a lock around your work, and have the waiter take that lock to see if the work was done or being done...
... in which case the work will be boosted then. and if it hasn't been done yet, then do it yourself.

Oh one last thing, I forgot, it's obvious to me but not readers, dispatch_once() is built on top of os_unfair_lock and admits an owner, and is priority inversion safe.

Note: NSOperation and many other higher level subsystem use dispatch/XPC under the cover and have some amount of QoS propagation as a result, so the list above covers a _LOT_ of things in the OS obviously. but the QoS propagation is really only funnelled through these.
Missing some Tweet in this thread? You can try to force a refresh.

Enjoying this thread?

Keep Current with Pierre Habouzit

Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!

This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!