Non-preemptive scheduling on Windows

DSP, Plug-in and Host development discussion.
Resplendence
KVRist
241 posts since 29 Sep, 2007 from Europe

Post Fri Feb 14, 2020 11:24 pm

I've been checking the behavior of some well-known DAWs and other audio software and to my surprise I found none of them have a specific job object associated with them. This means that they run with a default scheduling class (scheduling class is not the same as priority) so they will not get a favorable treatment from the scheduler and the feature of non-preemptive scheduling is disabled.

Setting the priorty class and the thread priority to THREAD_PRIORITY_TIME_CRITICAL is only part of what needs to be done to get a favorable treatment from the scheduler. Your thread will still compete for CPU time with other threads running at the highest priority such as system threads.

Windows offers a not so well known feature called non-preemptive scheduling. It allows threads running at the highest priority to have their quantums disabled so that these threads never expire and they will never get preempted by any other thread in the system. Of course they can still be preempted by interrupts and DPCs but at least it allows you to defeat any other threads in the system (including system kernel threads).

The trick to achieve this is by setting the scheduling class to a value of 9 by means of a job object. If a value of 9 is detected, the kernel will set a special flag in the process object so that it will receive a treatment of non-preemptive scheduling by the scheduler.

While this is not exactly documented at MSDN, in the WRK this is described as follows: "If quantum runout is disabled for the thread's process and the thread is
running at a realtime priority, then set the thread quantum to the highest value and do not round robin at the thread's priority level. Otherwise, reset the thread quantum and decay the thread's priority as appropriate"
Anybody who wants to look this up with a kernel debugger, the flag is called "DisableQuantum" and the routine that sets this flag "KeSetDisableQuantumProcess".
This feature has been there since the initial version of Windows NT.


Here's how to achieve non-preemptive scheduling on Windows.

1) Call SetPriorityClass for the process with REALTIME_PRIORITY_CLASS
2) Call SetThreadPriority with THREAD_PRIORITY_TIME_CRITICAL
3) Let the process enable the SeIncreaseBasePriorityPrivilege (using LookupPrivilegeValue and AdjustTokenPrivileges)
4) Create a job object for the process (CreateJobObject). The job can be unnamed.
5) call QueryInformationJobObject with JobObjectBasicLimitInformation
6) Set LimitFlags member of the JOBOBJECT_BASIC_LIMIT_INFORMATION to JOB_OBJECT_LIMIT_SCHEDULING_CLASS
7) Set the SchedulingClass member to 9. Only if a value of 9 is chosen, the magic of non-preemptive scheduling is enabled for the process.
8) Call SetInformationJobObject (JobObjectBasicLimitInformationwith) with these values
9) Associate your process with the job by using OpenProcess and AssignProcessToJobObject.

If you're a DAW developer or otherwise run threads at the highest priority, I hope you will find this information useful and take your advantage so your application can benefit from a treatment of non-preemptive scheduling.

Chaotikmind
KVRist
70 posts since 26 Sep, 2005 from France

Re: Non-preemptive scheduling on Windows

Post Fri Feb 14, 2020 11:45 pm

If you start doing that for all audio processing thread in a daw, you will probably freeze the computer more than anything else.
the UI still need to stay fluid/responsive.
Not sure it is worth it unless you use a single audio thread.

Resplendence
KVRist
241 posts since 29 Sep, 2007 from Europe

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 12:22 am

You don't want the UI to update at the expense of a critical audio thread. Or we would not be using priorities at all.

User avatar
BertKoor
KVRAF
11578 posts since 8 Mar, 2005 from Utrecht, Holland

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 5:10 am

Resplendence wrote:
Sat Feb 15, 2020 12:22 am
You don't want the UI to update at the expense of a critical audio thread. Or we would not be using priorities at all.
You do want the UI to stay responsive, despite an audio thread in the background.

Your proposal is a good recipe for a DAW that cannot be stopped in any way. Try it...
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is back online!!

Resplendence
KVRist
241 posts since 29 Sep, 2007 from Europe

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 5:35 am

You simply cannot have more critical threads running at the same time than there are processors available in the system. This is regardless of whether those threads are having a super-realtime priority or not. The time that we are running on uniprocessor systems is long gone.

mystran
KVRAF
5606 posts since 12 Feb, 2006 from Helsinki, Finland

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 4:47 pm

Resplendence wrote:
Fri Feb 14, 2020 11:24 pm
Setting the priorty class and the thread priority to THREAD_PRIORITY_TIME_CRITICAL is only part of what needs to be done to get a favorable treatment from the scheduler. Your thread will still compete for CPU time with other threads running at the highest priority such as system threads.

Windows offers a not so well known feature called non-preemptive scheduling. It allows threads running at the highest priority to have their quantums disabled so that these threads never expire and they will never get preempted by any other thread in the system. Of course they can still be preempted by interrupts and DPCs but at least it allows you to defeat any other threads in the system (including system kernel threads).
I don't think you can disable pre-emptive scheduling for user-space threads. The function you quote is a kernel API and one should be really careful with such APIs even in the kernel, because you can literally freeze the whole system if something goes wrong.

That said, on modern Windows (ie. Vista and later, at least with MMCSS running) you actually won't even get a proper (user-space) real-time thread with THREAD_PRIORITY_TIME_CRITICAL, rather that will just give you the highest possible regular priority (just below the real-time classes). On a system that is not running too much other crap besides audio, this is often "good enough" but it's not really the right thing to do either.

Instead, what you are actually supposed to do is call the MMCSS functions, specifically AvSetMmThreadCharacteristics and set the characteristic to "Pro Audio" class. This will then cause the MMCSS service to bump your thread to a proper real-time priority (and "Pro Audio" class gets the most favourable treatment of anything you can do in user-space), while monitoring the CPU usage to make sure that it doesn't starve the rest of the system (ie. if you eat more than 90% CPU or whatever it's set at in the registry, then MMCSS will temporarily drop the priority, to make sure the GUI doesn't freeze).

Also in general, having more processing threads than CPUs is generally perfectly fine, except as far as there will be some overhead from context switches, so matching the number of processing threads to the number of physical cores typically gives you the best performance, but even then having a slight over-commitment will usually give you speed-up over letting some cores sit idle.
Please just let me die.

Resplendence
KVRist
241 posts since 29 Sep, 2007 from Europe

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 6:22 pm

mystran wrote:
Sat Feb 15, 2020 4:47 pm
I don't think you can disable pre-emptive scheduling for user-space threads.
Yes you can.
The function you quote is a kernel API and one should be really careful with such APIs even in the kernel
It wasn't suggested that you call these routines yourself, you'd need a driver to do that. These routines are called under the hood as soon as you associate a process with a job object that has certain properties set (scheduling class). The job routines are documented user-mode routines. Like many other routines, they do their work in kernelmode under the hood.
Instead, what you are actually supposed to do is call the MMCSS functions, specifically AvSetMmThreadCharacteristics and set the characteristic to "Pro Audio" class.
Note that the priorities reserved for Pro Audio tasks are 23-26 which they say is lower than only certain system-level tasks but in reality is lower than any thread with THREAD_PRIORITY_TIME_CRITICAL.

mystran
KVRAF
5606 posts since 12 Feb, 2006 from Helsinki, Finland

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 6:55 pm

Resplendence wrote:
Sat Feb 15, 2020 6:22 pm
Note that the priorities reserved for Pro Audio tasks are 23-26 which they say is lower than only certain system-level tasks but in reality is lower than any thread with THREAD_PRIORITY_TIME_CRITICAL.
THREAD_PRIORITY_TIME_CRITICAL puts you at priority 15 unless the whole DAW is running in PRIORITY_CLASS_REALTIME which is (1) stupid idea and (2) requires Administrator priviledges. MMCSS can put a thread into a real-time class (in a safe way), it's specifically designed for this particular purpose and it's a great thing, because you no longer need to risk buggy real-time applications (eg. plugins) freezing your system permanently.

The idea of using a driver to put a user-space thread into a scheduling class it's not supposed to have (why do you think the API is not available in user-space) is just beyond retarded and demonstrates a very fundamental lack of understanding about how operating systems actually function. Fortunately DAW vendors aren't idiots.
Please just let me die.

Resplendence
KVRist
241 posts since 29 Sep, 2007 from Europe

Re: Non-preemptive scheduling on Windows

Post Sat Feb 15, 2020 7:15 pm

The idea of using a driver to put a user-space thread into a scheduling class it's not supposed to have (why do you think the API is not available in user-space) is just beyond retarded and demonstrates a very fundamental lack of understanding about how operating systems actually function. Fortunately DAW vendors aren't idiots.
You should really read before replying. I wrote this that the job functions are available in user space and that no driver is required.

Chaotikmind
KVRist
70 posts since 26 Sep, 2005 from France

Re: Non-preemptive scheduling on Windows

Post Sun Feb 16, 2020 9:37 am

Resplendence wrote:
Sat Feb 15, 2020 7:15 pm
The idea of using a driver to put a user-space thread into a scheduling class it's not supposed to have (why do you think the API is not available in user-space) is just beyond retarded and demonstrates a very fundamental lack of understanding about how operating systems actually function. Fortunately DAW vendors aren't idiots.
You should really read before replying. I wrote this that the job functions are available in user space and that no driver is required.
Nevertheless it is a worse idea that it seems at first glance.
try it, and see the results....

Otherwise don't you think a lot of people would be doing it ???
it is not like a lot of dsp people here are system illiterate , right?

Resplendence
KVRist
241 posts since 29 Sep, 2007 from Europe

Re: Non-preemptive scheduling on Windows

Post Sun Feb 16, 2020 9:53 pm

Chaotikmind wrote:
Sun Feb 16, 2020 9:37 am
it is not like a lot of dsp people here are system illiterate , right?
Unfortunately. They don't know what they don't know. Not knowing the in-depth details about job object properties doesn't make one system illiterate though.

Return to “DSP and Plug-in Development”