Mutex API

API Reference


The Mutex API provides standard mutex functionality with added diagnostics capabilities. These mutexes can be shared by threads within the same process, but can't be shared by threads in different processes.

Warning
Multithreaded programming is an advanced subject with many pitfalls. A general discussion of why and how mutexes are used in multithreaded programming is beyond the scope of this documentation. If you are not familiar with these concepts please seek out training and mentorship before attempting to work on multithreaded production code.

Two kinds of mutex are supported by Legato:

  • Normal
  • Traceable

Normal mutexes are faster than traceable mutexes and consume less memory, but still offer some diagnosic capabilities. Traceable mutexes generally behave the same as Normal mutexes, but can also log their activities.

In addition, both Normal and Traceable mutexes can be either

  • Recursive or
  • Non-Recursive

All mutexes can be locked and unlocked. The same lock, unlock, and delete functions work for all the mutexes, regardless of what type they are. his means that a mutex can be changed from Normal to Traceable (or vice versa) by changing the function you use to create it. This helps to troubleshoot race conditions or deadlocks because it's easy to switch one mutex or a select few mutexes to Traceable without suffering the runtime cost of switching all mutexes to the slower Traceable mutexes.

A recursive mutex can be locked again by the same thread that already has the lock, but a non-recursive mutex can only be locked once before being unlocked.

If a thread grabs a non-recursive mutex lock and then tries to grab that same lock again, a deadlock occurs. Legato's non-recursive mutexes will detect this deadlock, log a fatal error and terminate the process.

If a thread grabs a recursive mutex, and then the same thread grabs the same lock again, the mutex's "lock count" is incremented. When the thread unlocks that mutex, the lock count is decremented. Only when the lock count reaches zero will the mutex actually unlock.

There's a limit to the number of times the same recursive mutex can be locked by the same thread without ever unlocking it, but that limit is so high (at least 2 billion), if that much recursion is going on, there are other, more serious problems with the program.

Creating a Mutex

In Legato, mutexes are dynamically allocated objects. Functions that create them return references to them (of type le_mutex_Ref_t).

These are the functions to create mutexes:

All mutexes have names, required for diagnostic purposes. See Diagnostics below.

Using a Mutex

These are the functions to lock and unlock mutexes:

It doesn't matter what type of mutex you are using, you still use the same functions for locking and unlocking your mutex.

Tip

A common case is often where a module has a single mutex it uses for some data structure that may get accessed by multiple threads. To make the locking and unlocking of that mutex jump out at readers of the code (and to make coding a little easier too), the following can be created in that module:

static le_mutex_Ref_t MyMutexRef;
static inline Lock(void) { le_mutex_Lock(MyMutexRef); }
static inline Unlock(void) { le_mutex_Unlock(MyMutexRef); }

This results in code that looks like this:

static void SetParam(int param)
{
Lock();
MyObjPtr->param = param;
Unlock();
}

To make this easier, the Mutex API provides the LE_MUTEX_DECLARE_REF() macro. Using that macro, the three declaration lines

static le_mutex_Ref_t MyMutexRef;
static inline Lock(void) { le_mutex_Lock(MyMutexRef); }
static inline Unlock(void) { le_mutex_Unlock(MyMutexRef); }

can be replaced with one:

Deleting a Mutex

When you are finished with a mutex, you must delete it by calling le_mutex_Delete().

There must not be anyone using the mutex when it is deleted (i.e., no one can be holding it).

Diagnostics

Both Normal and Traceable mutexes have some diagnostics capabilities.

The command-line diagnostic tool lsmutex can be used to list the mutexes that currently exist inside a given process. The state of each mutex can be seen, including a list of any threads that might be waiting for that mutex.

The tool threadlook will report if a given thread is currently holding the lock on a mutex or waiting for a mutex along with the mutex name.

If there are Traceable mutexes in a process, it's possible to use the log tool to enable or disable tracing on that mutex. The trace keyword name is the name of the process, the name of the component, and the name of the mutex, separated by slashes (e.g., "process/component/mutex").


Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.