[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

General Programming Concepts: Writing and Debugging Programs

Threads Scheduling

Each thread has its own set of scheduling parameters. These parameters can be set using the thread attributes object before the thread's creation. They can also be dynamically set during the thread's execution.

Read the following to learn more about threads scheduling:

Basic Scheduling Facilities

Controlling the scheduling of a thread is often a complicated task. Because the scheduler handles all threads systemwide, 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.

Inheritsched Attribute

The inheritsched attribute of the thread attributes object specifies how the thread's scheduling attributes will be defined. It may have one of the following values:

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 must first be set to PTHREAD_EXPLICIT_SCHED. Otherwise, the attributes object scheduling attributes are ignored.

Scheduling Policy and Priority

The threads library provides three scheduling policies:

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 a 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.

The default scheduling policy for threads is SCHED_OTHER.

The priority is an integer value, in the range from 1 to 127. 1 is the least-favored priority, 127 is the most-favored. Priority level 0 cannot be used: it is reserved for the system. Note that 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. 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. Currently, this structure contains two fields:

sched_priority Specifies the priority.
sched_policy This field is ignored by the threads library and should not be used.

In the future, other fields may be defined for other scheduling characteristics.

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 three previously defined scheduling policies. The current value of the schedpolicy attribute of a thread attributes object can be obtained by 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_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &schedparam);

pthread_create(&thread, &attr, &start_routine, &args);

See Inheritsched Attribute to get more information about the inheritsched attribute.

Setting the Scheduling Attributes at Execution Time

The current schedpolicy and schedparam attributes of a thread are returned by the pthread_getschedparam subroutine. 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 may be scheduled immediately at the end of the subroutine call.

For example, consider a thread T that is currently running with RR 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 pthread_setschedparam, the target thread will be scheduled immediately if it is the highest priority runnable thread.

Note: Both subroutines use two parameters: 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 ignore the sched_policy field.

Considerations about Scheduling Policies

Applications should use the default scheduling policy, unless a specific application requires the use of a fixed-priority scheduling policy.

Using the RR 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 have to 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 RR policy may not always be allowed. See Impacts of Contention Scope on Scheduling for more information.

Contention Scope

The threads library defines two possible contention scopes:

PTHREAD_SCOPE_PROCESS Process (or local) contention scope. Specifies that the thread will be scheduled against all other local contention scope threads in the process.
PTHREAD_SCOPE_SYSTEM System (or global) contention scope. Specifies that the thread will be scheduled against all other threads in the system.

See Threads Implementation for more information about contention scope.

Setting the Contention Scope

The contention scope can only be set before thread creation by setting the contention-scope attribute of a thread attributes object. The pthread_attr_setscope subroutine sets the value of the attribute; the pthread_attr_getscope returns it.

The contention scope is only meaningful in a mixed-scope M:N library implementation. A single-scope 1:1 library implementation, as in Pre-AIX 4.3, always returns an error when trying to set the contention-scope attribute to PTHREAD_SCOPE_PROCESS, because all threads have system contention scope. This is the easiest way to test the implementation of a threads library. A TestImplementation routine could be written as follows:

int TestImplementation()
        pthread_attr_t a;
        int result;

        switch (pthread_attr_setscope(&a, PTHREAD_SCOPE_PROCESS))
                case 0:          result = LIB_MN; break;
                case ENOTSUP:    result = LIB_11; break;
                case ENOSYS:     result = NO_PRIO_OPTION; break;
                default:         result = ERROR; break;

        return result;

Prior to AIX 4.3, this routine would return LIB_11.

In AIX 4.3, this routine returns LIB_MN.

Impacts of Contention Scope on Scheduling

The contention scope of a thread influences its scheduling. Each system contention scope thread is bound to one kernel thread. Thus changing the scheduling policy and priority of a global user thread results in changing the scheduling policy and priority of the underlying kernel thread.

In AIX, only kernel threads with root authority can use a fixed-priority scheduling policy (FIFO or RR). The following code:

schedparam.sched_priority = 3;
pthread_setschedparam(pthread_self(), SCHED_FIFO, schedparam);

will always return the EPERM error code if the calling thread has system contention scope but does not have root authority. It would not fail, if the calling thread had process contention scope. One does not need to have root authority to control the scheduling parameters of user threads with process contention scope.

Local user thread can set any scheduling policy and priority, within the valid range of values. However, two threads having the same scheduling policy and priority but having different contention scope will not be scheduled in the same way. Threads having process contention scope are executed by kernel threads whose scheduling parameters are set by the library.

sched_yield Subroutine

The sched_yield subroutine is the equivalent for threads of the yield subroutine. It forces the calling thread to relinquish the use of its processor. It gives other threads a chance to be scheduled. The next scheduled thread may belong to the same process as the calling thread or to another process. The yield subroutine must not be used in a multi-threaded program.

The interface pthread_yield subroutine is not available in XOPEN VERSION 5.

Related Information

Thread Programming Concepts

Scheduling Overview

Synchronization Scheduling

"List of Scheduling Subroutines".

Threads Library Options

[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]