Pthread
Last updated
Last updated
Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University
POSIX Threads is abbreviated as Pthreads. POSIX is the abbreviation of "Portable Operating System Interface". POSIX is a set of standards developed by the IEEE Computer Society to improve the compatibility of different operating systems and the portability of applications. Pthreads is the POSIX standard for threads, which is defined in the POSIX.1c, Threads extensions (IEEE Std1003.1c-1995) standard, which defines a set of types, functions and constants for the C programming language. There are about 100 APIs defined in the pthread.h header file and a thread library. All APIs have the "pthread_" prefix and can be divided into 4 categories:
Thread management: includes functions for creating, detaching, joining, setting and querying thread properties, etc.
Mutex: Abbreviation of "mutual exclusion", used to restrict thread access to shared data and protect the integrity of shared data. Includes functions for creating, destroying, locking and unlocking mutexes and some functions for setting or modifying mutex properties.
Condition variable: used for communication between threads that share a mutex. It includes functions for creating, destroying, waiting, and sending signals for condition variables.
Read/write locks and barriers: including functions for creating, destroying, waiting, and setting related properties of read/write locks and barriers.
POSIX semaphores are used with Pthreads, but are not part of the Pthreads standard. They are defined in the POSIX.1b, Real-time extensions (IEEE Std1003.1b-1993) standard. Therefore, the prefix of semaphore-related functions is "sem_" instead of "pthread_".
Message queues, like semaphores, are used with Pthreads and are not part of the Pthreads standard definition. They are defined in the IEEE Std 1003.1-2001 standard. The prefix of message queue related functions is "mq_".
Most Pthreads functions return a value of 0 if they are executed successfully, and an error code included in the header file if they are not executed successfully errno.h
. Many operating systems support Pthreads, such as Linux, MacOSX, Android, and Solaris, so applications written using Pthreads functions have good portability and can be directly compiled and run on many platforms that support Pthreads.
The POSIX API interface used in RT-Thread includes several parts: libc (such as newlib), filesystem, pthread, etc.
Enable pthread in menuconfig and set the maximum number of pthreads supported
In user code, you can use pthread.h, sche.h
the header files provided by pthread to program
RT-Thread implements most of the functions and constants of Pthreads, which are defined in the pthread.h, mqueue.h, semaphore.h and sched.h header files according to the POSIX standard. Pthreads is a sub-library of libc. Pthreads in RT-Thread is a wrapper based on RT-Thread kernel functions to make it compliant with the POSIX standard. The following chapters will introduce the Pthreads functions and related functions implemented in RT-Thread in detail.
pthread_t is a redefinition of the rt_thread_t type, defined in the pthread.h header file. rt_thread_t is the thread handle (or thread identifier) of RT-Thread, which is a pointer to the thread control block. Before creating a thread, you need to define a variable of type pthread_t. Each thread corresponds to its own thread control block. The thread control block is a data structure used by the operating system to control threads. It stores some thread information, such as priority, thread name, and thread stack address. The thread control block and thread specific information are described in detail in the Thread Scheduling and Management chapter of the RT-Thread Programming Manual.
This function creates a pthread thread. This function will dynamically allocate POSIX thread data blocks and RT-Thread thread control blocks, and save the starting address of the thread control block (thread ID) in the memory pointed to by the parameter tid. This thread identifier can be used to operate this thread in other threads; and save the thread attributes pointed to by attr, the thread entry function pointed to by start, and the entry function parameter arg in the thread data block and thread control block. If the thread is created successfully, the thread immediately enters the ready state and participates in the system scheduling. If the thread creation fails, the resources previously occupied by the thread will be released.
Thread properties and related functions are introduced in detail in the chapter on advanced thread programming. In general, the default properties can be used.
Note
Note: After creating a pthread, if the thread needs to be created and used repeatedly, you need to set the pthread to detach mode, or use pthread_join to wait for the created pthread to end.
The following program will initialize 2 threads, they have a common entry function, but their entry parameters are different. Otherwise, they have the same priority and are scheduled in round-robin fashion using time slices.
When this function is called, if the pthread thread has not ended, the detached state of the thread thread attribute will be set to detached; when the thread thread has ended, the system will reclaim the resources occupied by the pthread thread.
Usage: The child thread calls pthread_detach(pthread_self()) (pthread_self() returns the thread handle of the current calling thread), or other threads call pthread_detach(thread_id). The detached state of thread attributes will be described in detail later.
Note
Note: Once the thread attribute's detached state is set to detached, the thread cannot be waited for by the pthread_join() function or set to detached again.
The following program will initialize 2 threads with the same priority and schedule them in round-robin mode. Both threads will be set to the detached state, and will automatically exit after printing information 3 times in a loop. After exiting, the system will automatically recycle its resources.
This function will make the calling thread wait in a blocking manner for the thread whose thread detachment attribute is joinable to finish running, and obtain the return value of thread. The address of the return value is saved in value_ptr, and the resources occupied by thread are released.
The functions of pthread_join() and pthread_detach() are similar, and are used to reclaim the resources occupied by the thread after the thread ends. A thread cannot wait for itself to end. The detachment state of the thread must be joinable, and one thread only corresponds to one pthread_join()
call. The resources occupied by a thread with a detachment state of joinable will be released only when other threads execute it pthread_join()
. Therefore, in order to avoid memory leaks, all threads that will end their operation must either have their detachment state set to detached or use pthread_join() to reclaim their occupied resources.
Waiting for the thread to end sample code
The following program code will initialize 2 threads with the same priority. Threads with the same priority are scheduled in round-robin fashion according to the time slice. The separation state of the 2 thread attributes is the default value of joinable. Thread 1 starts running first and ends after printing information three times in a loop. Thread 2 calls pthread_join() to block and wait for thread 1 to end, and reclaim the resources occupied by thread 1. Then thread 2 prints information every 2 seconds.