Developing multithreaded programs
Developing multithreaded programs is similar to developing programs with multiple processes. Developing programs also consists of compiling and debugging the code.
Compiling a multithreaded program
- The required header file
- Invoking the compiler, which is used to generate multithreaded programs.
Header file
All subroutine prototypes, macros, and other definitions for using the threads library are in the pthread.h header file, which is located in the /usr/include directory. The pthread.h header file must be included in each source file using the threads library.
The pthread.h header includes the unistd.h header, which provides the following global definitions:
- _POSIX_REENTRANT_FUNCTIONS
- Specifies that all functions should be reentrant. Several header files use this symbol to define supplementary reentrant subroutines, such as the localtime_r subroutine.
- _POSIX_THREADS
- Denotes the POSIX threads API. This symbol is used to check if the POSIX threads API is available. Macros or subroutines may be defined in different ways, depending on whether the POSIX or some other threads API is used.
The pthread.h file also includes errno.h, in which the errno global variable is redefined to be thread-specific. The errno identifier is, therefore, no longer an l-value in a multithreaded program.
Invoking the compiler
- xlc_r
- Invokes the compiler with default language level of ansi
- cc_r
- Invokes the compiler with default language level of extended
These commands ensure that the adequate options and libraries are used to be compliant with the Single UNIX Specification, Version 2. The POSIX Threads Specification 1003.1c is a subset of the Single UNIX Specification, Version 2.
- libpthreads.a
- Threads library
- libc.a
- Standard C library
cc_r -o foo foo.c
Invoking the compiler for draft 7 of POSIX 1003.1c
AIX® provides source code compatibility for Draft 7 applications. It is recommended that developers port their threaded application to the latest standard.
- xlc_r7
- Invokes the compiler with default language level of ansi
- cc_r7
- Invokes the compiler with default language level of extended
- libpthreads_compat.a
- Draft 7 Compatibility Threads library
- libpthreads.a
- Threads library
- libc.a
- Standard C library
To achieve source code compatibility, use the compiler directive _AIX_PTHREADS_D7. It is also necessary to link the libraries in the following order: libpthreads_compat.a, libpthreads.a, and libc.a. Most users do not need to know this information, because the commands provide the necessary options. These options are provided for those who do not have the latest AIX compiler.
Porting draft 7 applications to the &Symbol.unixspec;
- Minor errno differences. The most prevalent is the use of ESRCH to denote the specified pthread could not be found. Draft 7 frequently returned EINVAL for this failure.
- The default state when a pthread is created is joinable. This is a significant change because it can result in a memory leak if ignored.
- The default pthread scheduling parameter is scope.
- The pthread_yield subroutine has been replaced by the sched_yield subroutine.
- The various scheduling policies associated with the mutex locks are slightly different.
Memory requirements of a multithreaded program
Data Model | -bmaxdata | Maximum Pthreads |
---|---|---|
Small Data | n/a | 1084 |
Big Data | 0x10000000 | 2169 |
Big Data | 0x20000000 | 4340 |
Big Data | 0x30000000 | 6510 |
Big Data | 0x40000000 | 8681 |
Big Data | 0x50000000 | 10852 |
Big Data | 0x60000000 | 13022 |
Big Data | 0x70000000 | 15193 |
Big Data | 0x80000000 | 17364 |
Example of a multithreaded program
#include <pthread.h> /* include file for pthreads - the 1st */
#include <stdio.h> /* include file for printf() */
#include <unistd.h> /* include file for sleep() */
void *Thread(void *string)
{
while (1)
printf("%s\n", (char *)string);
pthread_exit(NULL);
}
int main()
{
char *e_str = "Hello!";
char *f_str = "Bonjour !";
pthread_t e_th;
pthread_t f_th;
int rc;
rc = pthread_create(&e_th, NULL, Thread, (void *)e_str);
if (rc)
exit(-1);
rc = pthread_create(&f_th, NULL, Thread, (void *)f_str);
if (rc)
exit(-1);
sleep(5);
/* usually the exit subroutine should not be used
see below to get more information */
exit(0);
}
The initial thread (executing the main routine) creates two threads. Both threads have the same entry-point routine (the Thread routine), but a different parameter. The parameter is a pointer to the string that will be displayed.
Debugging a multithreaded program
- Application programmers can use the dbx command to perform debugging. Several subcommands are available for displaying thread-related objects, including attribute, condition, mutex, and thread.
- Kernel programmers can use the
kernel debug program to perform debugging on kernel extensions and
device drivers. The kernel debug program provides limited access to
user threads, and primarily handles kernel threads. Several subcommands
support multiple kernel threads and processors, including:
- The cpu subcommand, which changes the current processor
- The ppd subcommand, which displays per-processor data structures
- The thread subcommand, which displays thread table entries
- The uthread subcommand, which displays the uthread structure of a thread
Core File requirements of a multithreaded program
chdev -l sys0 -a fullcore=true
Each individual pthread adds to the size of the generated core file. The amount of core file space that a pthread needs includes the stack size, which the user can control with the pthread_attr_setstacksize subroutine. For pthreads created with the NULL pthread attribute, each pthread in a 32-bit process adds 128 KB to the size of the core file, and each pthread in a 64-bit process adds 256 KB to the size of the core file.