Scheduling threads

Threads can be scheduled, and the threads library provides several facilities to handle and control the scheduling of threads.

It also provides facilities to control the scheduling of threads during synchronization operations such as locking a mutex. Each thread has its own set of scheduling parameters. These parameters can be set using the thread attributes object before the thread is created. The parameters can also be dynamically set during the thread's execution.

Controlling the scheduling of a thread can be a complicated task. Because the scheduler handles all threads system wide, the scheduling parameters of a thread interact with those of all other threads in the process and in the other processes. The following facilities are the first to be used if you want to control the scheduling of a thread.

The threads library allows the programmer to control the execution scheduling of the threads in the following ways:
  • By setting scheduling attributes when creating a thread
  • By dynamically changing the scheduling attributes of a created thread
  • By defining the effect of a mutex on the thread's scheduling when creating a mutex (known as synchronization scheduling)
  • By dynamically changing the scheduling of a thread during synchronization operations (known as synchronization scheduling)

Scheduling parameters

A thread has the following scheduling parameters:

Parameter Description
scope The contention scope of a thread is defined by the thread model used in the threads library.
policy The scheduling policy of a thread defines how the scheduler treats the thread after it gains control of the CPU.
priority The scheduling priority of a thread defines the relative importance of the work being done by each thread.

The scheduling parameters can be set before the thread's creation or during the thread's execution. In general, controlling the scheduling parameters of threads is important only for threads that are CPU-intensive. Thus, the threads library provides default values that are sufficient for most cases.

Using the inheritsched attribute

The inheritsched attribute of the thread attributes object specifies how the thread's scheduling attributes will be defined. The following values are valid:

Values Description
PTHREAD_INHERIT_SCHED Specifies that the new thread will get the scheduling attributes (schedpolicy and schedparam attributes) of its creating thread. Scheduling attributes defined in the attributes object are ignored.
PTHREAD_EXPLICIT_SCHED Specifies that the new thread will get the scheduling attributes defined in this attributes object.

The default value of the inheritsched attribute is PTHREAD_INHERIT_SCHED. The attribute is set by calling the pthread_attr_setinheritsched subroutine. The current value of the attribute is returned by calling the pthread_attr_getinheritsched subroutine.

To set the scheduling attributes of a thread in the thread attributes object, the inheritsched attribute must first be set to PTHREAD_EXPLICIT_SCHED. Otherwise, the attributes-object scheduling attributes are ignored.

Scheduling policy and priority

The threads library provides the following scheduling policies:

Library Description
SCHED_FIFO First-in first-out (FIFO) scheduling. Each thread has a fixed priority; when multiple threads have the same priority level, they run to completion in FIFO order.
SCHED_RR Round-robin (RR) scheduling. Each thread has a fixed priority; when multiple threads have the same priority level, they run for a fixed time slice in FIFO order.
SCHED_OTHER Default AIX® scheduling. Each thread has an initial priority that is dynamically modified by the scheduler, according to the thread's activity; thread execution is time-sliced. On other systems, this scheduling policy may be different.

In versions of AIX prior to 5.3, changing the priority of a thread when setting its scheduling policy to SCHED_OTHER is not permitted. In this case, the kernel directly manages the priority, and the only legal value that can be passed to the pthread_setschedparam subroutine is the DEFAULT_PRIO value. The DEFAULT_PRIO value is defined in pthread.h file as 1, and any other passed values are ignored.

Beginning with AIX 5.3, you can change the priority of a thread when you set its scheduling policy to SCHED_OTHER. The legal values that can be passed to the pthread_setschedparam subroutine are from 40 to 80, however, only privileged users can set a priority greater than 60. A priority in the range of 1 to 39 provides the same priority as that of 40, and a priority in the range of 81 to 127 provides the same priority as that of 80.

Note: In AIX, the kernel inverts the priority levels. For the AIX kernel, the priority is in the range from 0 to 127, where 0 is the most favored priority and 127 the least favored priority. Commands, such as the ps command, report the kernel priority.
The threads library handles the priority through a sched_param structure, defined in the sys/sched.h header file. This structure contains the following fields:
Fields Description
sched_priority Specifies the priority.
sched_policy This field is ignored by the threads library. Do not use.

Setting the scheduling policy and priority at creation time

The scheduling policy can be set when creating a thread by setting the schedpolicy attribute of the thread attributes object. The pthread_attr_setschedpolicy subroutine sets the scheduling policy to one of the previously defined scheduling policies. The current value of the schedpolicy attribute of a thread attributes object can be obtained by using the pthread_attr_getschedpolicy subroutine.

The scheduling priority can be set at creation time of a thread by setting the schedparam attribute of the thread attributes object. The pthread_attr_setschedparam subroutine sets the value of the schedparam attribute, copying the value of the specified structure. The pthread_attr_getschedparam subroutine gets the schedparam attribute.

In the following code fragment, a thread is created with the round-robin scheduling policy, using a priority level of 3:
sched_param schedparam;

schedparam.sched_priority = 3;

pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &schedparam);

pthread_create(&thread, &attr, &start_routine, &args);
pthread_attr_destroy(&attr);
For more information about the inheritsched attribute, see Using the inheritsched Attribute.

Setting the scheduling attributes at execution time

The pthread_getschedparam subroutine returns the schedpolicy and schedparam attributes of a thread. These attributes can be set by calling the pthread_setschedparam subroutine. If the target thread is currently running on a processor, the new scheduling policy and priority will be implemented the next time the thread is scheduled. If the target thread is not running, it can be scheduled immediately at the end of the subroutine call.

For example, consider a thread T that is currently running with round-robin policy at the moment the schedpolicy attribute of T is changed to FIFO. T will run until the end of its time slice, at which time its scheduling attributes are then re-evaluated. If no threads have higher priority, T will be rescheduled, even before other threads having the same priority. Consider a second example where a low-priority thread is not running. If this thread's priority is raised by another thread calling the pthread_setschedparam subroutine, the target thread will be scheduled immediately if it is the highest priority runnable thread.

Note: Both subroutines use a policy parameter and a sched_param structure. Although this structure contains a sched_policy field, programs should not use it. The subroutines use the policy parameter to pass the scheduling policy, and the subroutines then ignore the sched_policy field.

Scheduling-policy considerations

Applications should use the default scheduling policy, unless a specific application requires the use of a fixed-priority scheduling policy. Consider the following points about using the nondefault policies:
  • Using the round-robin policy ensures that all threads having the same priority level will be scheduled equally, regardless of their activity. This can be useful in programs where threads must read sensors or write actuators.
  • Using the FIFO policy should be done with great care. A thread running with FIFO policy runs to completion, unless it is blocked by some calls, such as performing input and output operations. A high-priority FIFO thread may not be preempted and can affect the global performance of the system. For example, threads doing intensive calculations, such as inverting a large matrix, should never run with FIFO policy.

The setting of scheduling policy and priority is also influenced by the contention scope of threads. Using the FIFO or the round-robin policy may not always be allowed.

sched_yield subroutine

The sched_yield subroutine is the equivalent for threads of the yield subroutine. The sched_yield subroutine forces the calling thread to relinquish the use of its processor and gives other threads an opportunity to be scheduled. The next scheduled thread may belong to the same process as the calling thread or to another process. Do not use the yield subroutine in a multithreaded program.

The interface pthread_yield subroutine is not available in Single UNIX Specification, Version 2.