TNeo  v1.09
Data Structures | Enumerations | Functions
tn_mutex.h File Reference

Detailed Description

A mutex is an object used to protect shared resources.

There is a lot of confusion about the differences between semaphores and mutexes, so, it's highly recommended that you read a small article by Michael Barr: Mutexes and Semaphores Demystified.

Very short:

While a mutex is seemingly similar to a semaphore with a maximum count of 1 (the so-called binary semaphore), their usage is very different: the purpose of mutex is to protect a shared resource. A locked mutex is "owned" by the task that locked it, and only that same task may unlock it. This ownership allows you to implement algorithms to prevent priority inversion. So, a mutex is a locking mechanism.

A semaphore, on the other hand, is a signaling mechanism. It's quite legal and encouraged for a semaphore to be acquired in task A, and then signaled from task B or even from an ISR. It may be used in situations like "producer and consumer", etc.

In addition to the article mentioned above, you may want to look at the related question on stackoverflow.com.


Mutex features in TNeo:

A discussion about the strengths and weaknesses of each protocol as well as the priority inversions problem is beyond the scope of this document.

The priority inheritance protocol solves the priority inversion problem, but doesn't prevent deadlocks. However, the kernel can notify you if a deadlock has occurred (see #TN_MUTEX_DEADLOCK_DETECT).

The priority ceiling protocol prevents deadlocks and chained blocking but it is slower than the priority inheritance protocol.

See also
#TN_USE_MUTEXES

Definition in file tn_mutex.h.

Go to the source code of this file.

Data Structures

struct  TN_Mutex
 Mutex. More...
 

Enumerations

enum  TN_MutexProtocol { TN_MUTEX_PROT_CEILING = 1, TN_MUTEX_PROT_INHERIT = 2 }
 Mutex protocol for avoid priority inversion. More...
 

Functions

enum TN_RCode tn_mutex_create (struct TN_Mutex *mutex, enum TN_MutexProtocol protocol, int ceil_priority)
 Construct the mutex. More...
 
enum TN_RCode tn_mutex_delete (struct TN_Mutex *mutex)
 Destruct mutex. More...
 
enum TN_RCode tn_mutex_lock (struct TN_Mutex *mutex, TN_TickCnt timeout)
 Lock mutex. More...
 
enum TN_RCode tn_mutex_lock_polling (struct TN_Mutex *mutex)
 The same as tn_mutex_lock() with zero timeout. More...
 
enum TN_RCode tn_mutex_unlock (struct TN_Mutex *mutex)
 Unlock mutex. More...
 

Enumeration Type Documentation

◆ TN_MutexProtocol

Mutex protocol for avoid priority inversion.

Enumerator
TN_MUTEX_PROT_CEILING 

Mutex uses priority ceiling protocol.

TN_MUTEX_PROT_INHERIT 

Mutex uses priority inheritance protocol.

Definition at line 109 of file tn_mutex.h.

Function Documentation

◆ tn_mutex_create()

enum TN_RCode tn_mutex_create ( struct TN_Mutex mutex,
enum TN_MutexProtocol  protocol,
int  ceil_priority 
)

Construct the mutex.

The field id_mutex should not contain #TN_ID_MUTEX, otherwise, #TN_RC_WPARAM is returned.

(refer to Legend for details)

Parameters
mutexPointer to already allocated struct TN_Mutex
protocolMutex protocol: priority ceiling or priority inheritance. See enum #TN_MutexProtocol.
ceil_priorityUsed if only protocol is #TN_MUTEX_PROT_CEILING: maximum priority of the task that may lock the mutex.
Returns

  • #TN_RC_OK if mutex was successfully created;
  • If #TN_CHECK_PARAM is non-zero, additional return code is available: #TN_RC_WPARAM.

◆ tn_mutex_delete()

enum TN_RCode tn_mutex_delete ( struct TN_Mutex mutex)

Destruct mutex.

All tasks that wait for lock the mutex become runnable with #TN_RC_DELETED code returned.

(refer to Legend for details)

Parameters
mutexmutex to destruct
Returns
  • #TN_RC_OK if mutex was successfully destroyed;
  • #TN_RC_WCONTEXT if called from wrong context;
  • If #TN_CHECK_PARAM is non-zero, additional return codes are available: #TN_RC_WPARAM and #TN_RC_INVALID_OBJ.

◆ tn_mutex_lock()

enum TN_RCode tn_mutex_lock ( struct TN_Mutex mutex,
TN_TickCnt  timeout 
)

Lock mutex.

  • If the mutex is not locked, function immediately locks the mutex and returns #TN_RC_OK.
  • If the mutex is already locked by the same task, lock count is merely incremented and #TN_RC_OK is returned immediately.
  • If the mutex is locked by different task, behavior depends on timeout value: refer to #TN_TickCnt.

(refer to Legend for details)

Parameters
mutexmutex to lock
timeoutrefer to #TN_TickCnt
Returns
  • #TN_RC_OK if mutex is successfully locked or if lock count was merely incremented (this is possible if recursive locking is enabled, see #TN_MUTEX_REC)
  • #TN_RC_WCONTEXT if called from wrong context;
  • #TN_RC_ILLEGAL_USE
    • if mutex protocol is #TN_MUTEX_PROT_CEILING and calling task's priority is higher than ceil_priority given to tn_mutex_create()
    • if recursive locking is disabled (see #TN_MUTEX_REC) and the mutex is already locked by calling task
  • Other possible return codes depend on timeout value, refer to #TN_TickCnt
  • If #TN_CHECK_PARAM is non-zero, additional return codes are available: #TN_RC_WPARAM and #TN_RC_INVALID_OBJ.
See also
#TN_MutexProtocol

◆ tn_mutex_lock_polling()

enum TN_RCode tn_mutex_lock_polling ( struct TN_Mutex mutex)

The same as tn_mutex_lock() with zero timeout.

(refer to Legend for details)

◆ tn_mutex_unlock()

enum TN_RCode tn_mutex_unlock ( struct TN_Mutex mutex)

Unlock mutex.

  • If mutex is not locked or locked by different task, #TN_RC_ILLEGAL_USE is returned.
  • If mutex is already locked by calling task, lock count is decremented. Now, if lock count is zero, mutex gets unlocked (and if there are task(s) waiting for mutex, the first one from the wait queue locks the mutex). Otherwise, mutex remains locked with lock count decremented and function returns #TN_RC_OK.

(refer to Legend for details)

Returns
  • #TN_RC_OK if mutex is unlocked of if lock count was merely decremented (this is possible if recursive locking is enabled, see #TN_MUTEX_REC)
  • #TN_RC_WCONTEXT if called from wrong context;
  • #TN_RC_ILLEGAL_USE if mutex is either not locked or locked by different task
  • If #TN_CHECK_PARAM is non-zero, additional return codes are available: #TN_RC_WPARAM and #TN_RC_INVALID_OBJ.