8.2. POSIX threads (Pthreads) on AIX

AIX supports the following standards:

  • The Single UNIX Specification Version 2

    The specification includes the POSIX thread standard, known as the IEEE POSIX 1003.1c standard.[2] Thread implementations that conform to this standard are referred to as POSIX threads or Pthreads.[3]

    [2] AIX has been supporting the IEEE POSIX 1003.1c standard since Version 4.3. Later, it was included in the Single UNIX Specification Version 2, which AIX has been supporting since Version 5.1.

    [3] Currently, AIX does not support the POSIX thread option real-time extension.

  • The Open Group UNIX 98 specification[4]

    [4] AIX has been supporting the UNIX 98 specification since Version 4.3.

    The specification defines many additional functions on the former UNIX 95 specification, as well as extended threads functions over POSIX threads, based on industry input from major UNIX vendors.

On AIX, POSIX threads are defined as a set of C language programming types and sub-routine calls, implemented with a header file (/usr/include/pthread.h) and the POSIX thread library (/usr/lib/libpthreads.a).

AIX provides binary compatibility for existing multi-threaded applications that were written for the draft of Version 7 of the POSIX threads standard. The compatibility POSIX thread library,/usr/lib/libpthreads_compat.a, is only provided for backward compatibility for those applications. The compatibility POSIX thread library supports 32-bit applications only.

Both libraries are included in the bos.rte.libpthreads fileset, which is installed by default, as shown in the following example:

# lslpp -w /usr/lib/libpthreads*.a
  File                                      Fileset                Type
  ---------------------------------------------------------------------------
  /usr/lib/libpthreads.a                    bos.rte.libpthreads    Symlink
  /usr/lib/libpthreads_compat.a             bos.rte.libpthreads    Symlink

8.2.1. Advantages of using Pthreads

The following are the advantages of using Pthreads:

  • The primary purpose of using Pthreads is to realize potential performance gains. POSIX threads can be created and managed with much less operating system overhead and system resources than creating and managing a process.

  • Inter-thread communication is more efficient and, in many cases, easier to use than inter-process communication.

  • Multi-threaded applications offer potential performance gains over non-threaded applications in several other ways:

    - Overlapping CPUwork with I/O: For example, a program may have sections where it is performing a long I/O operation. While one Pthread is waiting for an I/O system call to complete, CPU intensive work can be performed by other Pthreads.

    - Priority/Real-time scheduling: High priority jobs can be scheduled to supersede or interrupt lower priority jobs.

    - Asynchronous event handling: Jobs that service events of indeterminate frequency and duration can be interleaved. For example, a Web server can both transfer data from previous requests and manage the arrival of new requests.

  • POSIX threads provide the infrastructure to parallelize applications using OpenMP, as explained in Chapter 9, “Program parallelization using OpenMP” on page 335.

8.2.2. The POSIX threads API

The POSIX threads API is defined in the ANSI/IEEE POSIX 1003.1 standard. All identifiers in the Pthreads library begin with pthread_. The POSIX threads API contains over 60 subroutines. Brief descriptions about the POSIX threads sub-routines supported on AIX are provided in Appendix D, “Subroutine references for POSIX threads” on page 473.

Naming conventions

All the POSIX threads sub-routines are categorized into several groups distinguished by the following function name prefixes:

pthread_Threads and miscellaneous subroutines (see Table D-1 on page 474 and Table D-6 on page 481)
pthread_attr_Thread attributes objects (see Table D-2 on page 476)
pthread_mutex_Managing mutexes (see Table D-3 on page 477)
pthread_mutexattr_mutex attribute objects (see Table D-3 on page 477)
pthread_cond_Condition variables (see Table D-3 on page 477)
pthread_condattr_Condition attribute objects (see Table D-3 on page 477)
pthread_rwlock_Read/Write lock objects (see Table D-5 on page 480)
pthread_rwlockattr_Read/Write lock attributes (see Table D-5 on page 480)
pthread_key_Thread-specific data keys (see Table D-4 on page 479)

8.2.3. Multi- and single-threaded processes

On AIX, the scheduling entity is a kernel thread. A single kernel thread can be mapped to multiple user threads (Pthreads) within a process (detailed information about the relationship between kernel threads and user threads is provided in 8.7.1, “Thread models in AIX” on page 322).

In order to illustrate how multi-threaded applications run on AIX, we have excerpted several lines from the ps -emo THREAD command output, as shown in Example 8-1 on page 281. The -o THREAD option instructs the ps command to display thread-level information; without this option, the command displays process-level information only.

Each column in the output represents the following:

USERThe login name of the process owner.
PIDThe process ID of the process.
PPIDThe process ID of the parent process.
TIDThe thread ID of the kernel thread.
SThe state of the process or kernel thread.
CThe CPU utilization of the process or kernel thread.
PRIThe priority of the process or kernel thread.
SCThe suspend count of the process or kernel thread.
WCHANThe wait channel of the process or kernel thread.
FLAGThe flags of the process or kernel thread.
TTYThe controlling terminal of the process.
BNDThe CPU to which the process or kernel thread is bound.
CMDThe command being executed by the process.

Example 8-1. ps -emo THREAD
# ps -emo THREAD
    USER   PID  PPID    TID ST  CP  PRI  SC    WCHAN        F    TT  BND COMMAND
    root     1     0      - A    0   60   1        -   200003     -    - /etc/init
       -     -     -    259 S    0   60   1        -   410410     -    - -
... (some lines are omitted) ...
    root 10432 13686      - A    0   60  11 f015ab98   240001     -    - /usr/sbin/rpc.mountd
       -     -     -  19881 S    0   60   1 f015ab98   c10400     -    - -
       -     -     -  23811 Z    0   60   1        -   c00001     -    - -
       -     -     -  49449 Z    0   60   1        -   c00001     -    - -
       -     -     -  53961 Z    0   60   1        -   c00001     -    - -
       -     -     -  54215 Z    0   60   1        -   c00001     -    - -
       -     -     -  55603 S    0   60   1        -   418400     -    - -
       -     -     -  60085 Z    0   60   1        -   c00001     -    - -
       -     -     -  60705 Z    0   60   1        -   c00001     -    - -
       -     -     -  62039 Z    0   60   1        -   c00001     -    - -
       -     -     -  63481 Z    0   60   1        -   c00001     -    - -
       -     -     -  63955 Z    0   60   1        -   c00001     -    - -
... (some lines are omitted) ...
    root 16266 13686      - A    0   60   1 c0042100   240001     -    - /usr/sbin/qdaemon
       -     -     -  22197 S    0   60   1 c0042100    10400     -    - -
... (rest of lines are omitted) ...

In this example, the rpc.mountd daemon process (PID 10432) is a multi-threaded process, since it contains 11 lines underneath the highlighted line, while the qdaemon daemon process (PID 16266) is a single-threaded process, since it has only one line that represents the kernel thread for the process’s initial thread.

Two kernel threads (TID 19881 and 55603) of PID 10432 shown the status S, which means the kernel thread is in the sleeping status. Other kernel threads did not exist at the time the ps command was invoked, though TIDs were displayed.

the process could be verified by inspecting the /proc file system.[5] The /proc file system is a system interface to represent process information. The process information for the process <PID> is shown as several files and sub-directories under the /proc/<PID> directory.

[5] AIX has been supporting the /proc file system since AIX 5L Version 5.1.

As shown in Example 8-2 on page 282, there were only two sub-directories, 19881 and 55603, under the /proc/10432/Iwp directory[6] at the moment the ps command was invoked. The sub-directory names, 19881 and 55603, were the same TIDs for the PID 10432 in Example 8-1.

[6] LWP stands for light-weight process. In the /proc file system semantic, kernel threads are represented as LWPs.

Example 8-2. Inspecting the/proc file system
# ls /proc/10432
as       ctl      fd/     map      psinfo   status
cred     cwd@     lwp/    object/  sigact   sysent
# ls /proc/10432/lwp
19881/  55603/
# ls -lR /proc/10432/lwp
total 0
dr-xr-xr-x   1 root     system            0 Feb 21 18:41 19881/
dr-xr-xr-x   1 root     system            0 Feb 21 18:41 55603/
/proc/10432/lwp/19881:
total 0
--w-------   1 root     system            0 Feb 21 18:41 lwpctl
-r--r--r--   1 root     system          120 Feb 21 18:41 lwpsinfo
-r--------   1 root     system         1200 Feb 21 18:41 lwpstatus

/proc/10432/lwp/55603:
total 0
--w-------   1 root     system            0 Feb 21 18:41 lwpctl
-r--r--r--   1 root     system          120 Feb 21 18:41 lwpsinfo
-r--------   1 root     system         1200 Feb 21 18:41 lwpstatus

For further information about the /proc file system, please refer to the AIX 5L Version 5.2 Files Reference.

Although the rpc.mountd daemon process (PID 10432) was easily determined to be a multi-threaded process in Example 8-1 on page 281, in order to determine if the qdaemon daemon process (PID 16266) is non-threaded, use the ldd[7] command against the executable file, as shown in Example 8-3. Because qdaemon does not depend on the POSIX thread library, we are sure that it is not a multi-threaded program.

[7] The ldd command is supported on AIX 5L Version 5.2 and later. On earlier versions of AIX, use the dump -H command.

Example 8-3. Inspecting an executable file using ldd
# ldd /user/sbin/qdaemon
/usr/sbin/qdaemon needs:
         /usr/lib/libc.a(shr.o)
         /usr/lib/libqb.a(shr.o)
         /unix
         /usr/lib/libcrypt.a(shr.o)

Initial thread

When a process is created, one user thread is automatically created. This user thread is called the initial thread. It ensures the compatibility between the non-threaded processes with a unique implicit Pthread and the multi-threaded processes. The initial thread has some special properties, not visible to the programmer, that ensure binary compatibility between the non-threaded processes and the multi-threaded operating system. It is also the initial thread that executes the main function in multi-threaded programs.

Use of errno in multi-threaded programming

In the multi-process UNIX programming semantic, a system call or sub-routine would set a non-zero value to the global variable errno in case of failure. This is still true in multi-threaded programming, though there is a subtle difference.

Within a multi-threaded process, each Pthread has its own errno to avoid being overwritten by the other Pthreads. On AIX, the Pthread-basis errno is implemented as a macro to a function pointer to an internal function, as shown in Example 8-4, which is excerpted from /usr/include/errno.h.[8] In the multi-threaded programming on AIX, the_THREAD_SAFE macro is always defined.

[8] In the POSIX thread standard, the Pthread-basis errno is defined as implementation-dependent.

Example 8-4. Definition of errno
#if defined(_THREAD_SAFE) || defined(_THREAD_SAFE_ERRNO)
/*
 * Per thread errno is provided by the threads provider. Both the extern int
 * and the per thread value must be maintained by the threads library.
 */
extern  int *_Errno( void );
#define errno   (*_Errno())
#else
extern int errno;
#endif  /* _THREAD_SAFE || _THREAD_SAFE_ERRNO */

Although the process level global symbol errno is still accessible from Pthreads within a process, references to it is unreliable and useless in the multi-threaded programming.

Therefore, all the multi-threaded applications that reference to errno must have the following directive:

#include <errno.h>

and must not have the following declaration:

extern int errno;

Note

Avoid directly referencing the internal function, because this is implementation-dependent and may be subject to change in future versions of AIX. Use the errno macro to assure the portability of your multi-threaded applications.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset