Chapter 10. Thread synchronization mechanisms in RHEL for Real Time In real-time, when two or more threads need access to a shared resource at the same time, the threads coordinate using the thread synchronization mechanism. Thread synchronization ensures that only one thread uses the shared resource at a time. The three thread synchronization mechanisms used on Linux: Mutexes, Barriers, and Condition variables ( condvars ). 10.1. Mutexes Mutex derives from the terms mutual exclusion. The mutual exclusion object synchronizes access to a resource. It is a mechanism that ensures only one thread can acquire a mutex at a time. The mutex algorithm creates a serial access to each section of code, so that only one thread executes the code at any one time. Mutexes are created using an attribute object known as the mutex attribute object. It is an abstract object, which contains several attributes that depends on the POSIX options you choose to implement. The attribute object is defined with the pthread_mutex_t variable. The object stores the attributes defined for the mutex. The pthread_mutex_init(&my_mutex, &my_mutex_attr) , pthread_mutexattr_setrobust() and pthread_mutexattr_getrobust() functions return 0, when successful. On error, they return the error number. In real-time, you can either retain the attribute object to initialize more mutexes of the same type or you can clean up (destroy) the attribute object. The mutex is not affected in either case. Mutexes include the standard and advanced type of mutexes. Standard mutexes The real-time standard mutexes are private, non-recursive, non-robust, and non-priority inheritance capable mutexes. Initializing a pthread_mutex_t using pthread_mutex_init(&my_mutex, &my_mutex_attr) creates a standard mutex. When using the standard mutex type, your application may not benefit from the advantages provided by the pthreads API and the RHEL for Real Time kernel. Advanced mutexes Mutexes defined with additional capabilities are called advanced mutexes. Advanced capabilities include priority inheritance, robust behavior of a mutex, and shared and private mutexes. For example, for robust mutexes, initializing the pthread_mutexattr_setrobust() function, sets the robust attribute. Similarly, using the attribute PTHREAD_PROCESS_SHARED , allows any thread to operate on the mutex, provided the thread has access to its allocated memory. The attribute PTHREAD_PROCESS_PRIVATE sets a private mutex. A non-robust mutex does not release automatically and stays locked until you manually release it. Additional resources futex(7) man page on your system pthread_mutex_destroy(P) man page on your system 10.2. Barriers Barriers operate in a very different way when compared to other thread synchronization methods. The barriers define a point in the code where all active threads stop until all threads and processes reach this barrier. Barriers are used in situations when a running application needs to ensure that all threads have completed specific tasks before execution can continue. The barrier mutex in real-time, take following two variables: The first variable records the stop and pass state of the barrier. The second variable records the total number of threads that enter the barrier. The barrier sets the state to pass only when the specified number of threads reach the defined barrier. When the barrier state is set to pass , the threads and processes proceed further. The pthread_barrier_init() function allocates the required resources to use the defined barrier and initializes it with the attributes referenced by the attr attribute object. The pthread_barrier_init() and pthread_barrier_destroy() functions return the zero value, when successful. On error, they return an error number. 10.3. Condition variables In real-time, condition variables ( condvar ) is a POSIX thread construct that waits for a particular condition to be achieved before proceeding. In general, the signaled condition relates to the state of data that the thread shares with another thread. For example, a condvar can be used to signal a data entry into a processing queue and a thread waiting to process that data from the queue. Using the pthread_cond_init() function, you can initialize a condition variable. The pthread_cond_init() , pthread_cond_wait() , and pthread_cond_signal() functions return the zero value, when successful. On error, it returns the error number. 10.4. Mutex classes The mentioned mutex options provides guidance on the mutex classes to consider when writing or porting an application. Table 10.1. Mutex options Advanced mutexes Description Shared mutexes Defines shared access for multiple threads to acquire a mutex at a given time. Shared mutexes can create latency. The attribute is PTHREAD_PROCESS_SHARED . Private mutexes Ensures that only the threads created within the same process can access the mutex. The attribute is PTHREAD_PROCESS_PRIVATE . Real-time priority inheritance Sets the priority level of the lower priority task higher above a current higher priority task. When the task completes, it releases the resource and the task drops back to its original priority permitting the higher priority task to run. The attribute is PTHREAD_PRIO_INHERIT . Robust mutexes Sets the robust mutexes to release automatically when the owning thread would stop. The value substring NP in the string PTHREAD_MUTEX_ROBUST_NP , indicates that robust mutexes are non-POSIX or not portable Additional resources futex(7) man page on your system 10.5. Thread synchronization functions The mentioned list of function types and the description provides information on the functions to use for thread synchronization mechanisms for the real-time kernel. Table 10.2. Functions Function Description pthread_mutexattr_init(&my_mutex_attr) Initiates a mutex with attributes specified by attr . If attr is NULL, it applies the default mutex attributes. pthread_mutexattr_destroy(&my_mutex_attr) Destroys the specified mutex object. You can re-initialize with pthread_mutex_init() . pthread_mutexattr_setrobust() Specifies the PTHREAD_MUTEX_ROBUST attribute of a mutex. The PTHREAD_MUTEX_ROBUST attribute defines a thread that can stop without unlocking the mutex. A future call to own this mutex succeeds automatically and returns the value EOWNERDEAD to indicate that the mutex owner no longer exists. pthread_mutexattr_getrobust() Queries the PTHREAD_MUTEX_ROBUST attribute of a mutex. pthread_barrier_init() Allocates the required resources to use and initialize the barrier with attribute object attr . If attr is NULL, it applies the default values. pthread_cond_init() Initializes a condition variable. The cond argument defines the object to initiate with the attributes in the condition variable attribute object attr . If attr is NULL, it applies the default values. pthread_cond_wait() Blocks a thread execution until it receives a signal from another thread. In addition, a call to this function also releases the associated lock on mutex before blocking. The argument cond defines the pthread_cond_t object for a thread to block on. The mutex argument specifies the mutex to unblock. pthread_cond_signal() Unblocks at least one of the threads that are blocked on a specified condition variable. The argument cond specifies using the pthread_cond_t object to unblock the thread.

Commands: