POSIX compliant mutex. More...
#include <cmsis-plus/rtos/os.h>
Classes | |
class | attributes |
Mutex attributes. More... | |
class | attributes_recursive |
Recursive mutex attributes. More... | |
class | protocol |
Mutex protocols. More... | |
class | robustness |
Mutex robustness. More... | |
class | type |
Mutex types. More... | |
Public Types | |
using | count_t = uint16_t |
Type of variables holding mutex recursion counters. | |
using | protocol_t = uint8_t |
Type of variables holding mutex protocols. | |
using | robustness_t = uint8_t |
Type of variables holding mutex robustness. | |
using | type_t = uint8_t |
Type of variables holding mutex behaviours. | |
Public Member Functions | |
Constructors & Destructor | |
mutex (const attributes &attr=initializer_normal) | |
Construct a mutex object instance. | |
mutex (const char *name, const attributes &attr=initializer_normal) | |
Construct a named mutex object instance. | |
~mutex () | |
Destruct the mutex object instance. | |
Operators | |
bool | operator== (const mutex &rhs) const |
Compare mutexes. | |
Public Member Functions | |
result_t | lock (void) |
Lock/acquire the mutex. | |
result_t | try_lock (void) |
Try to lock/acquire the mutex. | |
result_t | timed_lock (clock::duration_t timeout) |
Timed attempt to lock/acquire the mutex. | |
result_t | unlock (void) |
Unlock/release the mutex. | |
thread::priority_t | prio_ceiling (void) const |
Get the priority ceiling of a mutex. | |
result_t | prio_ceiling (thread::priority_t prio_ceiling, thread::priority_t *old_prio_ceiling=nullptr) |
Change the priority ceiling of a mutex. | |
result_t | consistent (void) |
Mark mutex as consistent. | |
thread * | owner (void) |
Get the thread that owns the mutex. | |
type_t | type (void) |
Get the mutex type. | |
protocol_t | protocol (void) |
Get the mutex protocol. | |
robustness_t | robustness (void) |
Get the mutex robustness. | |
result_t | reset (void) |
Reset the mutex. | |
Public Member Functions | |
const char * | name (void) const |
Get object name. | |
Static Public Member Functions | |
Operators | |
static void * | operator new (std::size_t bytes) |
Allocate space for a new object instance using the RTOS system allocator. | |
static void * | operator new (std::size_t bytes, void *ptr) |
Emplace a new object instance. | |
static void * | operator new[] (std::size_t bytes) |
Allocate space for an array of new object instances using the RTOS system allocator. | |
static void * | operator new[] (std::size_t bytes, void *ptr) |
Emplace an array of new object instances. | |
static void | operator delete (void *ptr, std::size_t bytes) |
Deallocate the dynamically allocated object instance. using the RTOS system allocator. | |
static void | operator delete[] (void *ptr, std::size_t bytes) |
Deallocate the dynamically allocated array of object. instances using the RTOS system allocator. | |
Static Public Attributes | |
static const attributes | initializer_normal |
Default normal mutex initialiser. | |
static const attributes_recursive | initializer_recursive |
Default recursive mutex initialiser. | |
static constexpr count_t | max_count = 0xFFFF |
Constant with the maximum value for the recursion counter. | |
Friends | |
class | thread |
Get the current running thread. | |
POSIX compliant mutex.
A synchronisation object used to allow multiple threads to serialise their access to shared data. The name derives from the capability it provides; namely, mutual-exclusion. The thread that has locked a mutex becomes its owner and remains the owner until that same thread unlocks the mutex.
Many error conditions that can occur are not required to be detected by the implementation in order to let implementations trade off performance versus degree of error checking according to the needs of their specific applications and execution environment. As a general rule, conditions caused by the system (such as insufficient memory) are required to be detected, but conditions caused by an erroneously coded application (such as failing to provide adequate synchronisation to prevent a mutex from being deleted while in use) are specified to result in undefined behaviour.
A wide range of implementations is thus made possible. For example, an implementation intended for application debugging may implement all of the error checks, but an implementation running a single, provably correct application under very tight performance constraints in an embedded computer might implement minimal checks. An implementation might even be provided in two versions, similar to the options that compilers provide: a full-checking, but slower version; and a limited-checking, but faster version. To forbid this optionality would be a disservice to users.
By carefully limiting the use of "undefined behaviour" only to things that an erroneous (badly coded) application might do, and by defining that resource-not-available errors are mandatory, POSIX ensures that a fully-conforming application is portable across the full range of implementations, while not forcing all implementations to add overhead to check for numerous things that a correct program never does. When the behaviour is undefined, no error number is specified to be returned on implementations that do detect the condition. This is because undefined behaviour means anything can happen, which includes returning with any value (which might happen to be a valid, but different, error number). However, since the error number might be useful to application developers when diagnosing problems during application development, a recommendation is made in rationale that implementors should return a particular error number if their implementation does detect the condition.
Providing for static initialisation of statically allocated synchronisation objects allows modules with private static synchronisation variables to avoid runtime initialisation tests and overhead. Furthermore, it simplifies the coding of self-initialising modules. Such modules are common in C libraries, where for various reasons the design calls for self-initialisation instead of requiring an explicit module initialisation function to be called. An example use of static initialisation:
pthread_mutex_t
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition). Definition at line 52 of file os-mutex.h.
os::rtos::mutex::mutex | ( | const attributes & | attr = initializer_normal | ) |
Construct a mutex object instance.
[in] | attr | Reference to attributes. |
This constructor shall initialise a mutex object with attributes referenced by attr. If the attributes specified by attr are modified later, the mutex attributes shall not be affected. Upon successful initialisation, the state of the mutex object shall become initialised.
Only the mutex object itself may be used for performing synchronisation. It is not allowed to make copies of condition variable objects.
In cases where default mutex attributes are appropriate, the variables mutex::initializer_normal
or mutex::initializer_recursive
can be used to initialise mutex objects. The effect shall be equivalent to creating a mutex object with the default constructor.
If the attr attributes are modified after the mutex creation, the mutex attributes shall not be affected.
pthread_mutex_init()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 430 of file os-mutex.cpp.
os::rtos::mutex::mutex | ( | const char * | name, |
const attributes & | attr = initializer_normal |
||
) |
Construct a named mutex object instance.
[in] | name | Pointer to name. |
[in] | attr | Reference to attributes. |
This constructor shall initialise a mutex object with attributes referenced by attr. If the attributes specified by attr are modified later, the mutex attributes shall not be affected. Upon successful initialisation, the state of the mutex object shall become initialised.
Only the mutex object itself may be used for performing synchronisation. It is not allowed to make copies of condition variable objects.
In cases where default mutex attributes are appropriate, the variables mutex::initializer_normal
or mutex::initializer_recursive
can be used to initialise mutex objects. The effect shall be equivalent to creating a mutex object with the default constructor.
If the attr attributes are modified after the mutex creation, the mutex attributes shall not be affected.
pthread_mutex_init()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 466 of file os-mutex.cpp.
os::rtos::mutex::~mutex | ( | ) |
Destruct the mutex object instance.
This destructor shall destroy the mutex object; the object becomes, in effect, uninitialised. An implementation may cause the destructor to set the object to an invalid value.
It shall be safe to destroy an initialised mutex that is unlocked. Attempting to destroy a locked mutex results in undefined behaviour (for example it may trigger an assert).
pthread_mutex_destroy()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 526 of file os-mutex.cpp.
result_t os::rtos::mutex::consistent | ( | void | ) |
Mark mutex as consistent.
result::ok | The mutex was marked as consistent. |
EPERM | Cannot be invoked from an Interrupt Service Routines. |
EINVAL | The mutex object referenced by mutex is not robust or does not protect an inconsistent state. |
If the robust mutex is in an inconsistent state, the consistent()
function can be used to mark the state protected by the mutex referenced by mutex as consistent again.
If an owner of a robust mutex terminates while holding the mutex, the mutex becomes inconsistent and the next thread that acquires the mutex lock shall be notified of the state by the return value EOWNERDEAD
. In this case, the mutex does not become normally usable again until the state is marked consistent.
If the thread which acquired the mutex lock with the return value EOWNERDEAD
terminates before calling either consistent()
or unlock()
, the next thread that acquires the mutex lock shall be notified about the state of the mutex by the return value EOWNERDEAD
.
pthread_mutex_consistent()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 1466 of file os-mutex.cpp.
result_t os::rtos::mutex::lock | ( | void | ) |
Lock/acquire the mutex.
result::ok | The mutex was locked. |
EPERM | Cannot be invoked from an Interrupt Service Routines. |
ENOTRECOVERABLE | The state protected by the mutex is not recoverable.. |
EAGAIN | The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. |
EINVAL | The mutex was created with the protocol attribute having the value mutex::protocol::protect and the calling thread's priority is higher than the mutex's current priority ceiling. |
EOWNERDEAD | The mutex is a robust mutex and the process containing the previous owning thread terminated while holding the mutex lock. The mutex lock shall be acquired by the calling thread and it is up to the new owner to make the state consistent. |
EDEADLK | The mutex type is mutex::type::errorcheck and the current thread already owns the mutex. |
If the mutex is free, lock it. If the mutex is already locked by another thread, the calling thread shall block until the mutex becomes available. This operation shall return with the mutex object referenced by mutex in the locked state with the calling thread as its owner. If a thread attempts to relock a mutex that it has already locked, lock()
shall behave as described in the Relock column of the following table. If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, unlock()
shall behave as described in the Unlock When Not Owner column of the following table.
Mutex Type | Robustness | Relock | Unlock When Not Owner |
---|---|---|---|
normal | non-robust | deadlock | undefined behaviour |
normal | robust | deadlock | error |
errorcheck | either | error | error |
recursive | either | recursive | error |
default | non-robust | undefined | undefined behaviour |
default | robust | undefined | error |
Where the table indicates recursive behaviour, the mutex shall maintain the concept of a lock count. When a thread successfully acquires a mutex for the first time, the lock count shall be set to one. Every time a thread relocks this mutex, the lock count shall be incremented by one. Each time the thread unlocks the mutex, the lock count shall be decremented by one. When the lock count reaches zero, the mutex shall become available for other threads to acquire.
pthread_mutex_lock()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 955 of file os-mutex.cpp.
|
inlineinherited |
Get object name.
All objects return a non-null string; anonymous objects return "-"
.
Definition at line 759 of file os-decls.h.
|
inlinestaticinherited |
Deallocate the dynamically allocated object instance. using the RTOS system allocator.
ptr | Pointer to object. |
bytes | Number of bytes to deallocate. |
The deallocation function (3.7.4.2) called by a delete-expression to render the value of ptr invalid.
ptr shall be a null pointer or its value shall be a value returned by an earlier call to the (possibly replaced) operator new() which has not been invalidated by an intervening call to operator delete(void*).
If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to operator new.
The storage is deallocated using the RTOS system allocator.
Definition at line 122 of file os-inlines.h.
|
inlinestaticinherited |
Deallocate the dynamically allocated array of object. instances using the RTOS system allocator.
ptr | Pointer to array of objects. |
bytes | Number of bytes to deallocate. |
The deallocation function (3.7.4.2) called by the array form of a delete-expression to render the value of ptr invalid.
If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to operator new.
The storage is deallocated using the RTOS system allocator.
Definition at line 143 of file os-inlines.h.
|
inlinestaticinherited |
Allocate space for a new object instance using the RTOS system allocator.
bytes | Number of bytes to allocate. |
The allocation function (3.7.4.1) called by a new-expression (5.3.4) to allocate a storage of size bytes suitably aligned to represent any object of that size. Return a non-null pointer to suitably aligned storage (3.7.4).
The storage is allocated using the RTOS system allocator.
Definition at line 44 of file os-inlines.h.
|
inlinestaticinherited |
Emplace a new object instance.
bytes | Number of bytes to emplace. |
ptr | Pointer to location to emplace the object. |
The allocation function (3.7.4.1) called by a placement new-expression to allocate a storage of size bytes suitably aligned to represent any object of that size. Return a non-null pointer to suitably aligned storage (3.7.4).
The storage is allocated using the RTOS system allocator.
Definition at line 81 of file os-inlines.h.
|
inlinestaticinherited |
Allocate space for an array of new object instances using the RTOS system allocator.
bytes | Number of bytes to allocate. |
The allocation function (3.7.4.1) called by the array form of a new-expression (5.3.4) to allocate a storage of size bytes suitably aligned to represent any array object of that size or smaller.
The storage is allocated using the RTOS system allocator.
Definition at line 62 of file os-inlines.h.
|
inlinestaticinherited |
Emplace an array of new object instances.
bytes | Number of bytes to emplace. |
ptr | Pointer to location to emplace the object. |
The allocation function (3.7.4.1) called by the array form of a placement new-expression to allocate a storage of size bytes suitably aligned to represent any array object of that size or smaller.
The storage is allocated using the RTOS system allocator.
Definition at line 98 of file os-inlines.h.
|
inline |
Compare mutexes.
true | The given mutex is the same as this mutex. |
false | The mutexes are different. |
Identical mutexes should have the same memory address.
Definition at line 828 of file os-mutex.h.
|
inline |
Get the thread that owns the mutex.
nullptr
if not owned.Definition at line 837 of file os-mutex.h.
result_t os::rtos::mutex::prio_ceiling | ( | thread::priority_t | prio_ceiling, |
thread::priority_t * | old_prio_ceiling = nullptr |
||
) |
Change the priority ceiling of a mutex.
[in] | prio_ceiling | new priority. |
[out] | old_prio_ceiling | pointer to location where to store the previous priority; may be nullptr . |
result::ok | The priority was changed. |
EPERM | Cannot be invoked from an Interrupt Service Routines. |
ENOTRECOVERABLE | The state protected by the mutex is not recoverable.. |
EAGAIN | The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. |
EINVAL | The mutex was created with the protocol attribute having the value mutex::protocol::protect and the calling thread's priority is higher than the mutex's current priority ceiling. |
EOWNERDEAD | The mutex is a robust mutex and the process containing the previous owning thread terminated while holding the mutex lock. The mutex lock shall be acquired by the calling thread and it is up to the new owner to make the state consistent. |
EDEADLK | The mutex type is mutex::type::errorcheck and the current thread already owns the mutex. |
Attempt to lock the mutex as if by a call to lock()
, except that the process of locking the mutex need not adhere to the priority protect protocol. On acquiring the mutex it shall change the mutex's priority ceiling and then release the mutex as if by a call to unlock()
. When the change is successful, the previous value of the priority ceiling shall be returned in old_prio_ceiling
.
If prio_ceiling()
function fails, the mutex priority ceiling shall not be changed.
pthread_mutex_setprioceiling()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 1400 of file os-mutex.cpp.
thread::priority_t os::rtos::mutex::prio_ceiling | ( | void | ) | const |
Get the priority ceiling of a mutex.
Return the current priority ceiling of the mutex.
pthread_mutex_getprioceiling()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 1359 of file os-mutex.cpp.
|
inline |
Get the mutex protocol.
Definition at line 855 of file os-mutex.h.
result_t os::rtos::mutex::reset | ( | void | ) |
Reset the mutex.
result::ok | The mutex was reset. |
Return the mutex to the state right after creation. If there were threads waiting for this mutex, wakeup all, then clear the waiting list.
Definition at line 1503 of file os-mutex.cpp.
|
inline |
Get the mutex robustness.
Definition at line 864 of file os-mutex.h.
result_t os::rtos::mutex::timed_lock | ( | clock::duration_t | timeout | ) |
Timed attempt to lock/acquire the mutex.
[in] | timeout | Timeout to wait, in clock units (ticks or seconds). |
result::ok | The mutex was locked. |
EPERM | Cannot be invoked from an Interrupt Service Routines. |
ETIMEDOUT | The mutex could not be locked before the specified timeout expired. |
ENOTRECOVERABLE | The state protected by the mutex is not recoverable. |
EAGAIN | The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. |
EDEADLK | The mutex type is mutex::type::errorcheck and the current thread already owns the mutex. |
EINVAL | The process or thread would have blocked, and the timeout parameter is invalid. |
EOWNERDEAD | The mutex is a robust mutex and the process containing the previous owning thread terminated while holding the mutex lock. The mutex lock shall be acquired by the calling thread and it is up to the new owner to make the state consistent. |
If the mutex is already locked, the calling thread shall block until the mutex becomes available as in the lock()
function. If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait shall be terminated when the specified timeout expires.
The timeout shall expire after the number of time units (that is when the value of that clock equals or exceeds (now()+duration). The resolution of the timeout shall be the resolution of the clock on which it is based.
Under no circumstance shall the function fail with a timeout if the mutex can be locked immediately. The validity of the timeout need not be checked if the mutex can be locked immediately.
The clock used for timeouts can be specified via the clock
attribute. By default, the clock derived from the scheduler timer is used, and the durations are expressed in ticks.
As a consequence of the priority inheritance rules (for mutexes initialized with mutex::protocol::inherit
), if a timed mutex wait is terminated because its timeout expires, the priority of the owner of the mutex shall be adjusted as necessary to reflect the fact that this thread is no longer among the threads waiting for the mutex.
pthread_mutex_timedlock()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition). Definition at line 1152 of file os-mutex.cpp.
result_t os::rtos::mutex::try_lock | ( | void | ) |
Try to lock/acquire the mutex.
result::ok | The mutex was locked. |
EPERM | Cannot be invoked from an Interrupt Service Routines. |
ENOTRECOVERABLE | The state protected by the mutex is not recoverable.. |
EAGAIN | The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. |
EINVAL | The mutex was created with the protocol attribute having the value mutex::protocol::protect and the calling thread's priority is higher than the mutex's current priority ceiling. |
EOWNERDEAD | The mutex is a robust mutex and the process containing the previous owning thread terminated while holding the mutex lock. The mutex lock shall be acquired by the calling thread and it is up to the new owner to make the state consistent. |
EDEADLK | The mutex type is mutex::type::errorcheck and the current thread already owns the mutex. |
EWOULDBLOCK | The mutex could not be acquired because it was already locked. |
Try to lock the mutex as lock()
, except that if the mutex is currently locked (by any thread, including the current thread), the call shall return immediately. If the mutex type is mutex::type::recursive
and the mutex is currently owned by the calling thread, the mutex lock count shall be incremented by one and the try_lock()
function shall immediately return success.
If the mutex is robust and the owning thread terminated while holding the mutex lock, a call to try_lock()
may return the error value EOWNERDEAD
. In these cases, the mutex is locked by the thread but the state it protects is marked as inconsistent. The application should ensure that the state is made consistent for reuse and when that is complete call consistent()
. If the application is unable to recover the state, it should unlock the mutex without a prior call to consistent()
, after which the mutex is marked permanently unusable.
pthread_mutex_trylock()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition). Definition at line 1076 of file os-mutex.cpp.
|
inline |
Get the mutex type.
Definition at line 846 of file os-mutex.h.
result_t os::rtos::mutex::unlock | ( | void | ) |
Unlock/release the mutex.
result::ok | The mutex was unlocked. |
EPERM | Cannot be invoked from an Interrupt Service Routine; the mutex type is mutex::type::errorcheck or mutex::type::recursive , or the mutex is a robust mutex, and the current thread does not own the mutex. |
ENOTRECOVERABLE | The recursive mutex whose oner died was not marked consistent() before unlock() . |
The manner in which a mutex is released is dependent upon the mutex's type attribute. If there are threads blocked on the mutex object referenced by mutex when unlock()
is called, resulting in the mutex becoming available, the scheduling policy shall determine which thread shall acquire the mutex.
In the case of mutex::type::recursive
mutexes, the mutex shall become available when the count reaches zero and the calling thread no longer has any locks on this mutex.
pthread_mutex_unlock()
from <pthread.h>
(IEEE Std 1003.1, 2013 Edition).Definition at line 1324 of file os-mutex.cpp.
|
friend |
Get the current running thread.
Definition at line 600 of file os-mutex.h.