In this series, we are currently examining the different objects that exist within ThreadX to help developers synchronize events, tasks and move data around their applications. In this post, we are going to examine the mutex.
A mutex is used for mutual exclusion which is where its name comes from, MUTual EXclusion (MUTEX). A mutex provides a method for a thread to gain access to a shared resource or even to a critical code section. For example, a developer might want to use a mutex to protect a motor control state variable that can be changed by an HMI thread and used by a motor control thread to determine the state the motor should be. Clearly, if both threads could access this state variable at the same time it would be possible for a partially updated value from the HMI thread to be accessed by the motor control thread. This could result in a potentially dramatic error, and one difficult to track down! An example very similar to this is the BLDC Motor Control application project. The mutex provides access to the variable by a single thread at any given time.
The mutex is often considered to be a special binary semaphore but behind the scenes there are quite a few differences between mutexes and semaphores. When a thread locks a resource through a mutex, the thread is obtaining ownership over the mutex. A thread will own the mutex until it releases the resource by unlocking it. Semaphores don’t have this concept, they simply generate and consumer tokens. This means that for every mutex lock/get API call there will be a corresponding mutex release/put API call. Another important difference is that a mutex has a special capability known as priority inheritance that allows a threads priority to be elevated if a higher priority thread attempts to get the mutex. Priority inheritance is a technique that helps to minimize a priority inversion which is a common and potentially dangerous situation. In a future post, we will discuss what exactly a priority inversion is and how priority inheritance plays a role in minimizing the issue but for now just be aware that the feature exists.
Creating a mutex in the Renesas Synergy™ Platform development environment is similar to creating a semaphore. A developer opens the Synergy Configurator, navigates to the threads tab and then within the selected thread, adds a mutex. An example mutex from the BLDC application project can be seen below:
Once a mutex has been created, a developer can select the mutex and navigate to the Synergy properties window to create the initial settings. The mutex options can be seen below:
Developers can provide the mutex name and enable the priority inheritance feature. Disabling the priority inheritance mechanism is generally not recommended since the mutex at that point behaves just like a binary semaphore and loses its ability to minimize a priority inversion.
The nice part about the Synergy Platform is that developers don’t really need to care about the code that initializes the semaphore. Pressing the Generate Project Content button generates the code necessary to create the mutex in the application and developers only need to use their symbol name and the mutex APIs in their application.
There are several API’s that a developer can use to interact with the mutex object. These are detailed in the ThreadX user manual which can be downloaded from the Synergy Gallery. The primary API’s that we will discuss are the following:
UINT tx_mutex_put(TX_MUTEX *mutex_ptr)
UINT tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option)
The tx_mutex_put call will unlock the mutex and allow another thread to get access to the resource. The tx_mutex_get call will attempt to lock the mutex and get access to the resource. If the mutex has already been locked, there is an option to set how long the call will wait for the mutex to become available before moving on in the code execution. Developers can block forever on a mutex by using TX_WAIT_FOREVER or not block at all by using TX_NO_WAIT. It is highly recommended that you peruse the ThreadX user manual and examine the additional API’s that can be used with a mutex.
As was mentioned earlier, mutexes are great for providing mutual exclusion to a resource. In the BLDC application project, the update_state_data function attempts to update the state by first getting the mutex. If the attempt is successful the motor state is updated before putting the mutex. The example code can be seen shown below:
That covers the fundamentals that most engineers will need in order to start using mutexes in their applications. In the next post, we will look at event flags and discuss how they can be used instead of a semaphore in certain circumstances. Until next time,
Live long and profit!
Hot Tip of the Week
Don’t forget to download all the SSP 1.2.0 related material from the Synergy Gallery including the HTML version of the SSP User’s Manual, Upgrade documents and Datasheets available from the SSP Documentation Tab in the right-hand guide bar. Don’t overlook the SSP 1.2.0 updates to the most popular application projects. These are in the zip file at the end of the right-side guide bar. https://synergygallery.renesas.com/ssp/support#read