TNeo
BETA v1.08-11-g97e5a6d
|
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:
TN_MUTEX_REC
is non-zero);TN_MUTEX_DEADLOCK_DETECT
is non-zero);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.
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... | |
enum 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.
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.
mutex | Pointer to already allocated struct TN_Mutex |
protocol | Mutex protocol: priority ceiling or priority inheritance. See enum TN_MutexProtocol . |
ceil_priority | Used if only protocol is TN_MUTEX_PROT_CEILING : maximum priority of the task that may lock the mutex. |
TN_RC_OK
if mutex was successfully created;TN_CHECK_PARAM
is non-zero, additional return code is available: TN_RC_WPARAM
. Destruct mutex.
All tasks that wait for lock the mutex become runnable with TN_RC_DELETED
code returned.
mutex | mutex to destruct |
TN_RC_OK
if mutex was successfully destroyed;TN_RC_WCONTEXT
if called from wrong context;TN_CHECK_PARAM
is non-zero, additional return codes are available: TN_RC_WPARAM
and TN_RC_INVALID_OBJ
. enum TN_RCode tn_mutex_lock | ( | struct TN_Mutex * | mutex, |
TN_TickCnt | timeout | ||
) |
Lock mutex.
TN_RC_OK
.TN_RC_OK
is returned immediately.timeout
value: refer to TN_TickCnt
.mutex | mutex to lock |
timeout | refer to TN_TickCnt |
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
TN_MUTEX_PROT_CEILING
and calling task's priority is higher than ceil_priority
given to tn_mutex_create()
TN_MUTEX_REC
) and the mutex is already locked by calling tasktimeout
value, refer to TN_TickCnt
TN_CHECK_PARAM
is non-zero, additional return codes are available: TN_RC_WPARAM
and TN_RC_INVALID_OBJ
.TN_MutexProtocol
Unlock mutex.
TN_RC_ILLEGAL_USE
is returned.TN_RC_OK
.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 taskTN_CHECK_PARAM
is non-zero, additional return codes are available: TN_RC_WPARAM
and TN_RC_INVALID_OBJ
.