What Is Real Time Priority of a Process

What is the 'realtime' process priority setting for?

A realtime priority thread can never be pre-empted by timer interrupts and runs at a higher priority than any other thread in the system. As such a CPU bound realtime priority thread can totally ruin a machine.

Creating realtime priority threads requires a privilege (SeIncreaseBasePriorityPrivilege) so it can only be done by administrative users.

For Vista and beyond, one option for applications that do require that they run at realtime priorities is to use the Multimedia Class Scheduler Service (MMCSS) and let it manage your threads priority. The MMCSS will prevent your application from using too much CPU time so you don't have to worry about tanking the machine.

What is the 'realtime' process priority setting for

This is explained in Scheduling Priorities on MSDN (emphasis mine):

You should almost never use REALTIME_PRIORITY_CLASS, because this interrupts system threads that manage mouse input, keyboard input, and background disk flushing. This class can be appropriate for applications that "talk" directly to hardware or that perform brief tasks that should have limited interruptions.

So that's the theory. In practice, if you need to do this, you're probably doing something wrong.

Which real-time priority is the highest priority in Linux

I did an experiment to nail this down, as follows:

  • process1: RT priority = 40, CPU affinity = CPU 0. This process "spins" for 10 seconds so it won't let any lower-priority process run on CPU 0.

  • process2: RT priority = 39, CPU affinity = CPU 0. This process prints a message to stdout every 0.5 second, sleeping in between. It prints out the elapsed time with each message.

I'm running a 2.6.33 kernel with the PREEMPT_RT patch.

To run the experiment, I run process2 in one window (as root) and then start process1 (as root) in another window. The result is process1 appears to preempt process2, not allowing it to run for a full 10 seconds.

In a second experiment, I change process2's RT priority to 41. In this case, process2 is not preempted by process1.

This experiment shows that a larger RT priority value in sched_setscheduler() has a higher priority. This appears to contradict what Michael Foukarakis pointed out from sched.h, but actually it does not. In sched.c in the kernel source, we have:

static void
__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
{
BUG_ON(p->se.on_rq);

p->policy = policy;
p->rt_priority = prio;
p->normal_prio = normal_prio(p);
/* we are holding p->pi_lock already */
p->prio = rt_mutex_getprio(p);
if (rt_prio(p->prio))
p->sched_class = &rt_sched_class;
else
p->sched_class = &fair_sched_class;
set_load_weight(p);
}

rt_mutex_getprio(p) does the following:

return task->normal_prio;

While normal_prio() happens to do the following:

prio = MAX_RT_PRIO-1 - p->rt_priority;  /* <===== notice! */
...
return prio;

In other words, we have (my own interpretation):

p->prio = p->normal_prio = MAX_RT_PRIO - 1 - p->rt_priority

Wow! That is confusing! To summarize:

  • With p->prio, a smaller value preempts a larger value.

  • With p->rt_priority, a larger value preempts a smaller value. This is the real-time priority set using sched_setscheduler().

What's the difference between .NET Real-Time and TaskMgr Real-time priority class?

The real culprit here is Windows.

The setter of the PriorityClass property is straightforward:

 set {
if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
}

// BelowNormal and AboveNormal are only available on Win2k and greater.
if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0) &&
(OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
}

SafeProcessHandle handle = null;

try {
handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
throw new Win32Exception();
}
priorityClass = value;
havePriorityClass = true;
}
finally {
ReleaseProcessHandle(handle);
}
}

After a few sanity checks, it calls the Windows API SetPriorityClass, then it checks the return code. If an error occurs, it throws an exception. Otherwise, it stores locally the value of the new priority (so that, when you read the value of PriorityClass, it doesn't have to call Windows back to check it).

In some conditions, Windows will deny the change of priority (for instance, as you noticed, you now need administrator privileges to set the real-time priority). The trick is that Windows denies the priority change silently and does not return an error code. As documented here:

Note that the call to SetPriorityClass() may return success even though the priority was not set to REALTIME_PRIORITY_CLASS, because if you don't have the Increase Scheduling Priority permission, a request for REALTIME_PRIORITY_CLASS is interpreted as a request for the highest priority class allowed in the current account.

I'm guessing this is done to avoid breaking legacy applications that wouldn't expect their call to fail. Because of this, your .NET application is not aware that the priority change didn't work as expected, and returns the wrong value.


That said, even if Windows did set the priority as expected, the .NET code still wouldn't work in some cases. For instance, imagine you were setting the PriorityClass to BelowNormal. That value would be stored locally in the Process object, as explained above. Then if you change the priority again but from the task manager, just like before .NET won't be aware of it and will return the old value.

If you absolutely need an up-to-date information, first call process.Refresh() to clear the locally stored value.

What is real time priority of a process

if you are using the realtime scheduler (that means if an process runs controlled by the realtime scheduler), so the rtprio could be relevant.
Prio is relevant for the default scheduler sched

Normally RT processes has system-wide the highest priority by default. If you need to tune/coordinate RT processes and non-RT processes, so rtprio and prio have to be tuned.

http://www.gsp.com/cgi-bin/man.cgi?section=1&topic=rtprio
http://linux.die.net/man/2/sched_setscheduler

What effect does changing the process priority have in Windows?

It calls SetPriorityClass().

Every thread has a base priority level determined by the thread's
priority value and the priority class of its process. The system uses
the base priority level of all executable threads to determine which
thread gets the next slice of CPU time. The SetThreadPriority function
enables setting the base priority level of a thread relative to the
priority class of its process. For more information, see Scheduling
Priorities.

How to start executable with realtime priority?

It works when you are executing start as an administrator.

Technically, you need the SeIncreaseBasePriorityPrivilege, which an administrator normally has.
If you don't, it looks like albeit I couldn't find any documentation about that fact, that you are silently reverted to a priority that is still viable with the calling account.

I doubt that Win32 will help, as the same restrictions surely apply.

How to set real time priority with psutil

I had exactly the same problem, running python with "as Administrator" solved the issue (On Win10 with python3.7).

Create a windows shortcut to "python " and set "Run as administrator" in the Advanced settings of the shortcut.

How to Properly Use Realtime Priority

Well here's a start:

Invoke(DelegatedDisplay, Result);

This means that you are causing the background thread to wait until the UI thread actually performs the drawing operation, then proceed. From the thread's point of view that's an eternity. You might want to investigate asynchronous updates to the UI:

BeginInvoke(DelegatedDisplay, Result);

That's equivalent to telling the UI thread "when you have a chance, perform this drawing action", then proceeding with the work that you were doing.

You should be aware that this may cause thread-safety issues that didn't occur using Invoke, though. For example, if the background thread is still modifying Result while the UI is attempting to draw, you might have unexpected race conditions.

See Control.Invoke vs Control.BeginInvoke



Related Topics



Leave a reply



Submit