µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os::rtos::mutex_recursive Class Reference

POSIX compliant recursive mutex. More...

#include <cmsis-plus/rtos/os.h>

+ Inheritance diagram for os::rtos::mutex_recursive:

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_recursive (const attributes &attr=initializer_recursive)
 Construct a recursive mutex object instance.
 
 mutex_recursive (const char *name, const attributes &attr=initializer_recursive)
 Construct a named recursive mutex object instance.
 
 ~mutex_recursive ()
 Destruct the recursive mutex object instance.
 
Operators
bool operator== (const mutex_recursive &rhs) const
 Compare mutexes.
 
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.
 
threadowner (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.
 

Detailed Description

Definition at line 702 of file os-mutex.h.

Constructor & Destructor Documentation

◆ mutex_recursive() [1/2]

os::rtos::mutex_recursive::mutex_recursive ( const attributes attr = initializer_recursive)
inline
Parameters
[in]attrReference 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.

POSIX compatibility
Inspired by pthread_mutex_init() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 854 of file os-mutex.h.

855 : mutex{ attr }
856 {
857 }
mutex(const attributes &attr=initializer_normal)
Construct a mutex object instance.
Definition os-mutex.cpp:470

◆ mutex_recursive() [2/2]

os::rtos::mutex_recursive::mutex_recursive ( const char *  name,
const attributes attr = initializer_recursive 
)
inline

Definition at line 859 of file os-mutex.h.

861 : mutex{ name, attr }
862 {
863 }
const char * name(void) const
Get object name.
Definition os-decls.h:753

◆ ~mutex_recursive()

os::rtos::mutex_recursive::~mutex_recursive ( )
inline

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).

POSIX compatibility
Inspired by pthread_mutex_destroy() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 865 of file os-mutex.h.

866 {
867 }

Member Function Documentation

◆ consistent()

result_t os::rtos::mutex::consistent ( void  )
inherited
Parameters
None.
Return values
result::okThe mutex was marked as consistent.
EPERMCannot be invoked from an Interrupt Service Routines.
EINVALThe 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.

POSIX compatibility
Inspired by pthread_mutex_consistent() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1530 of file os-mutex.cpp.

1531 {
1532#if defined(OS_TRACE_RTOS_MUTEX)
1533 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1534#endif
1535
1536 // Don't call this from interrupt handlers.
1538 // Don't call this for non-robust mutexes.
1539 os_assert_err (robustness_ == robustness::robust, EINVAL);
1540 // Don't call it if already consistent.
1541 os_assert_err (!consistent_, EINVAL);
1542
1543#if defined(OS_USE_RTOS_PORT_MUTEX)
1544
1545 return port::mutex::consistent (this);
1546
1547#else
1548
1549 // Update status to consistent.
1550 consistent_ = true;
1551 return result::ok;
1552
1553#endif
1554 }
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1101
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:179
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1101
@ robust
Enhanced robustness at thread termination.
Definition os-mutex.h:125

References os::rtos::interrupts::in_handler_mode(), os::rtos::internal::object_named::name(), os::rtos::result::ok, os_assert_err, os::trace::printf(), and os::rtos::mutex::robustness::robust.

◆ lock()

result_t os::rtos::mutex::lock ( void  )
inherited
Parameters
None.
Return values
result::okThe mutex was locked.
EPERMCannot be invoked from an Interrupt Service Routines.
ENOTRECOVERABLEThe state protected by the mutex is not recoverable..
EAGAINThe mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
EINVALThe 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.
EOWNERDEADThe 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.
EDEADLKThe 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.

POSIX compatibility
Inspired by pthread_mutex_lock() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1003 of file os-mutex.cpp.

1004 {
1005#if defined(OS_TRACE_RTOS_MUTEX)
1006 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1008#endif
1009
1010 // Don't call this from interrupt handlers.
1012 // Don't try to lock a non-recursive mutex again.
1013 os_assert_err (!scheduler::locked (), EPERM);
1014
1015 if (!recoverable_)
1016 {
1017 return ENOTRECOVERABLE;
1018 }
1019
1020#if defined(OS_USE_RTOS_PORT_MUTEX)
1021
1022 return port::mutex::lock (this);
1023
1024#else
1025
1026 thread& crt_thread = this_thread::thread ();
1027
1028 result_t res;
1029 {
1030 // ----- Enter critical section ---------------------------------------
1031 scheduler::critical_section scs;
1032
1033 res = internal_try_lock_ (&crt_thread);
1034 if (res != EWOULDBLOCK)
1035 {
1036 return res;
1037 }
1038 // ----- Exit critical section ----------------------------------------
1039 }
1040
1041 // Prepare a list node pointing to the current thread.
1042 // Do not worry for being on stack, it is temporarily linked to the
1043 // list and guaranteed to be removed before this function returns.
1044 internal::waiting_thread_node node{ crt_thread };
1045
1046 for (;;)
1047 {
1048 {
1049 // ----- Enter critical section -----------------------------------
1050 scheduler::critical_section scs;
1051
1052 res = internal_try_lock_ (&crt_thread);
1053 if (res != EWOULDBLOCK)
1054 {
1055 return res;
1056 }
1057
1058 {
1059 // ----- Enter critical section -----------------------------
1060 interrupts::critical_section ics;
1061
1062 // Add this thread to the mutex waiting list.
1063 scheduler::internal_link_node (list_, node);
1064 // state::suspended set in above link().
1065 // ----- Exit critical section ------------------------------
1066 }
1067 // ----- Exit critical section ------------------------------------
1068 }
1069
1071
1072 // Remove the thread from the semaphore waiting list,
1073 // if not already removed by unlock().
1074 scheduler::internal_unlink_node (node);
1075
1076 if (crt_thread.interrupted ())
1077 {
1078#if defined(OS_TRACE_RTOS_MUTEX)
1079 trace::printf ("%s() EINTR @%p %s\n", __func__, this, name ());
1080#endif
1081 return EINTR;
1082 }
1083 }
1084
1085 /* NOTREACHED */
1086 return ENOTRECOVERABLE;
1087
1088#endif
1089 }
Standard thread.
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:858
thread & thread(void)
Get the current running thread.
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:95

References os::rtos::interrupts::in_handler_mode(), os::rtos::thread::interrupted(), os::rtos::scheduler::locked(), os::rtos::internal::object_named::name(), os_assert_err, os::trace::printf(), os::rtos::port::scheduler::reschedule(), and os::rtos::this_thread::thread().

Referenced by os::estd::mutex::lock(), os::estd::recursive_mutex::lock(), and os::rtos::mutex::prio_ceiling().

◆ name()

const char * os::rtos::internal::object_named::name ( void  ) const
inlineinherited
Parameters
None.
Returns
A null terminated string.

All objects return a non-null string; anonymous objects return "-".

Note
Can be invoked from Interrupt Service Routines.

Definition at line 753 of file os-decls.h.

754 {
755 return name_;
756 }

Referenced by os::memory::lifo::lifo(), os::memory::malloc_memory_resource::malloc_memory_resource(), os::rtos::message_queue_typed< T, Allocator >::message_queue_typed(), os::memory::block_pool::~block_pool(), os::rtos::event_flags::~event_flags(), os::memory::first_fit_top::~first_fit_top(), os::memory::lifo::~lifo(), os::memory::malloc_memory_resource::~malloc_memory_resource(), os::rtos::memory_pool::~memory_pool(), os::rtos::message_queue::~message_queue(), os::rtos::mutex::~mutex(), os::rtos::semaphore::~semaphore(), os::rtos::thread::~thread(), os::rtos::timer::~timer(), os::rtos::memory_pool::alloc(), os::rtos::thread::cancel(), os::rtos::event_flags::clear(), os::rtos::mutex::consistent(), os::rtos::thread::detach(), os::memory::new_delete_memory_resource::do_allocate(), os::memory::block_pool::do_allocate(), os::memory::first_fit_top::do_allocate(), os::memory::lifo::do_allocate(), os::memory::malloc_memory_resource::do_allocate(), os::rtos::thread::flags_raise(), os::rtos::memory_pool::free(), os::rtos::event_flags::get(), os::rtos::thread::interrupt(), os::rtos::thread::join(), os::rtos::thread::kill(), os::rtos::internal::terminated_threads_list::link(), os::rtos::mutex::lock(), os::rtos::memory::memory_resource::out_of_memory_handler(), os::rtos::semaphore::post(), os::rtos::mutex::prio_ceiling(), os::rtos::mutex::prio_ceiling(), os::rtos::thread::priority(), os::rtos::thread::priority_inherited(), os::rtos::event_flags::raise(), os::rtos::message_queue::receive(), os::rtos::memory_pool::reset(), os::rtos::message_queue::reset(), os::rtos::mutex::reset(), os::rtos::semaphore::reset(), os::rtos::thread::resume(), os::rtos::message_queue::send(), os::rtos::clock::sleep_for(), os::rtos::timer::start(), os::rtos::timer::stop(), os::rtos::memory_pool::timed_alloc(), os::rtos::mutex::timed_lock(), os::rtos::message_queue::timed_receive(), os::rtos::message_queue::timed_send(), os::rtos::semaphore::timed_wait(), os::rtos::event_flags::timed_wait(), os::rtos::memory::memory_resource::trace_print_statistics(), os::rtos::memory_pool::try_alloc(), os::rtos::mutex::try_lock(), os::rtos::message_queue::try_receive(), os::rtos::message_queue::try_send(), os::rtos::event_flags::try_wait(), os::rtos::semaphore::try_wait(), os::rtos::internal::ready_threads_list::unlink_head(), os::rtos::mutex::unlock(), os::rtos::event_flags::wait(), os::rtos::semaphore::wait(), and os::rtos::event_flags::waiting().

◆ operator delete()

void os::rtos::internal::object_named_system::operator delete ( void *  ptr,
std::size_t  bytes 
)
inlinestaticinherited
Parameters
ptrPointer to object.
bytesNumber of bytes to deallocate.
Returns
Nothing.

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.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 120 of file os-inlines.h.

121 {
122 assert (!interrupts::in_handler_mode ());
123
124 rtos::memory::allocator<char> ().deallocate (static_cast<char*> (ptr),
125 bytes);
126 }

References os::rtos::memory::allocator_stateless_default_resource< T >::deallocate(), and os::rtos::interrupts::in_handler_mode().

◆ operator delete[]()

void os::rtos::internal::object_named_system::operator delete[] ( void *  ptr,
std::size_t  bytes 
)
inlinestaticinherited
Parameters
ptrPointer to array of objects.
bytesNumber of bytes to deallocate.
Returns
Nothing.

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.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 141 of file os-inlines.h.

142 {
143 // Forward array deallocation to single element deallocation.
144 operator delete (ptr, bytes);
145 }

◆ operator new() [1/2]

void * os::rtos::internal::object_named_system::operator new ( std::size_t  bytes)
inlinestaticinherited
Parameters
bytesNumber of bytes to allocate.
Returns
Pointer to allocated object.

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.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 43 of file os-inlines.h.

44 {
45 assert (!interrupts::in_handler_mode ());
46
47 return rtos::memory::allocator<char> ().allocate (bytes);
48 }

References os::rtos::memory::allocator_stateless_default_resource< T >::allocate(), and os::rtos::interrupts::in_handler_mode().

◆ operator new() [2/2]

void * os::rtos::internal::object_named_system::operator new ( std::size_t  bytes,
void *  ptr 
)
inlinestaticinherited
Parameters
bytesNumber of bytes to emplace.
ptrPointer to location to emplace the object.
Returns
Pointer to emplaced 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.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 80 of file os-inlines.h.

81 {
82 return ptr;
83 }

◆ operator new[]() [1/2]

void * os::rtos::internal::object_named_system::operator new[] ( std::size_t  bytes)
inlinestaticinherited
Parameters
bytesNumber of bytes to allocate.
Returns
Pointer to allocated array.

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.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 61 of file os-inlines.h.

62 {
63 // Forward array allocation to single element allocation.
64 return operator new (bytes);
65 }

◆ operator new[]() [2/2]

void * os::rtos::internal::object_named_system::operator new[] ( std::size_t  bytes,
void *  ptr 
)
inlinestaticinherited
Parameters
bytesNumber of bytes to emplace.
ptrPointer to location to emplace the object.
Returns
Pointer to emplaced array.

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.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 97 of file os-inlines.h.

98 {
99 // Forward array allocation to single element allocation.
100 return operator new (bytes, ptr);
101 }

◆ operator==() [1/2]

bool os::rtos::mutex::operator== ( const mutex rhs) const
inlineinherited
Return values
trueThe given mutex is the same as this mutex.
falseThe mutexes are different.

Identical mutexes should have the same memory address.

Definition at line 811 of file os-mutex.h.

812 {
813 return this == &rhs;
814 }

◆ operator==() [2/2]

bool os::rtos::mutex_recursive::operator== ( const mutex_recursive rhs) const
inline
Return values
trueThe given mutex is the same as this mutex.
falseThe mutexes are different.

Identical mutexes should have the same memory address.

Definition at line 874 of file os-mutex.h.

875 {
876 return this == &rhs;
877 }

◆ owner()

thread * os::rtos::mutex::owner ( void  )
inlineinherited
Parameters
None.
Returns
Pointer to thread or nullptr if not owned.
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 820 of file os-mutex.h.

821 {
822 return owner_;
823 }

◆ prio_ceiling() [1/2]

result_t os::rtos::mutex::prio_ceiling ( thread::priority_t  prio_ceiling,
thread::priority_t old_prio_ceiling = nullptr 
)
inherited
Parameters
[in]prio_ceilingnew priority.
[out]old_prio_ceilingpointer to location where to store the previous priority; may be nullptr.
Return values
result::okThe priority was changed.
EPERMCannot be invoked from an Interrupt Service Routines.
ENOTRECOVERABLEThe state protected by the mutex is not recoverable..
EAGAINThe mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
EINVALThe 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.
EOWNERDEADThe 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.
EDEADLKThe 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.

POSIX compatibility
Inspired by pthread_mutex_setprioceiling() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1461 of file os-mutex.cpp.

1463 {
1464#if defined(OS_TRACE_RTOS_MUTEX)
1465 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1466#endif
1467
1468 // Don't call this from interrupt handlers.
1470
1471#if defined(OS_USE_RTOS_PORT_MUTEX)
1472
1473 return port::mutex::prio_ceiling (this, prio_ceiling, old_prio_ceiling);
1474
1475#else
1476
1477 // TODO: lock() must not adhere to the priority protocol.
1478 result_t res = lock ();
1479 if (res != result::ok)
1480 {
1481 return res;
1482 }
1483
1484 if (old_prio_ceiling != nullptr)
1485 {
1486 *old_prio_ceiling = prio_ceiling_;
1487 }
1488
1489 prio_ceiling_ = prio_ceiling;
1490
1491 unlock ();
1492
1493 return result::ok;
1494
1495#endif
1496 }
result_t lock(void)
Lock/acquire the mutex.
thread::priority_t prio_ceiling(void) const
Get the priority ceiling of a mutex.
result_t unlock(void)
Unlock/release the mutex.

References os::rtos::interrupts::in_handler_mode(), os::rtos::mutex::lock(), os::rtos::internal::object_named::name(), os::rtos::result::ok, os_assert_err, os::trace::printf(), os::rtos::mutex::prio_ceiling(), and os::rtos::mutex::unlock().

◆ prio_ceiling() [2/2]

thread::priority_t os::rtos::mutex::prio_ceiling ( void  ) const
inherited
Parameters
None.
Returns
The priority ceiling.

Return the current priority ceiling of the mutex.

POSIX compatibility
Inspired by pthread_mutex_getprioceiling() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1417 of file os-mutex.cpp.

1418 {
1419#if defined(OS_TRACE_RTOS_MUTEX)
1420 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1421#endif
1422
1423 // Don't call this from interrupt handlers.
1424 assert (!interrupts::in_handler_mode ());
1425
1426#if defined(OS_USE_RTOS_PORT_MUTEX)
1427
1428 return port::mutex::prio_ceiling (this);
1429
1430#else
1431
1432 return prio_ceiling_;
1433
1434#endif
1435 }

References os::rtos::interrupts::in_handler_mode(), os::rtos::internal::object_named::name(), and os::trace::printf().

Referenced by os::rtos::mutex::prio_ceiling().

◆ protocol()

mutex::protocol_t os::rtos::mutex::protocol ( void  )
inlineinherited
Returns
An integer encoding the mutex::protocol.
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 838 of file os-mutex.h.

839 {
840 return protocol_;
841 }

◆ reset()

result_t os::rtos::mutex::reset ( void  )
inherited
Parameters
None.
Return values
result::okThe 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.

POSIX compatibility
Extension to standard, no POSIX similar functionality identified.
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1567 of file os-mutex.cpp.

1568 {
1569#if defined(OS_TRACE_RTOS_MUTEX)
1570 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1571#endif
1572
1573 // Don't call this from interrupt handlers.
1575
1576 {
1577 // ----- Enter critical section ---------------------------------------
1578 scheduler::critical_section scs;
1579
1580 internal_init_ ();
1581 return result::ok;
1582 // ----- Exit critical section ----------------------------------------
1583 }
1584 }

References os::rtos::interrupts::in_handler_mode(), os::rtos::internal::object_named::name(), os::rtos::result::ok, os_assert_err, and os::trace::printf().

◆ robustness()

Returns
An integer encoding the mutex::robustness.
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 847 of file os-mutex.h.

848 {
849 return robustness_;
850 }

◆ timed_lock()

result_t os::rtos::mutex::timed_lock ( clock::duration_t  timeout)
inherited
Parameters
[in]timeoutTimeout to wait, in clock units (ticks or seconds).
Return values
result::okThe mutex was locked.
EPERMCannot be invoked from an Interrupt Service Routines.
ETIMEDOUTThe mutex could not be locked before the specified timeout expired.
ENOTRECOVERABLEThe state protected by the mutex is not recoverable.
EAGAINThe mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
EDEADLKThe mutex type is mutex::type::errorcheck and the current thread already owns the mutex.
EINVALThe process or thread would have blocked, and the timeout parameter is invalid.
EOWNERDEADThe 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.

POSIX compatibility
Inspired by pthread_mutex_timedlock() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Differences from the standard:
  • the timeout is not expressed as an absolute time point, but as a relative number of timer ticks (by default, the SysTick clock for Cortex-M).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1205 of file os-mutex.cpp.

1206 {
1207#if defined(OS_TRACE_RTOS_MUTEX)
1208#pragma GCC diagnostic push
1209#if defined(__clang__)
1210#elif defined(__GNUC__)
1211#pragma GCC diagnostic ignored "-Wuseless-cast"
1212#endif
1213 trace::printf ("%s(%u) @%p %s by %p %s\n", __func__,
1214 static_cast<unsigned int> (timeout), this, name (),
1216#pragma GCC diagnostic pop
1217#endif /* defined(OS_TRACE_RTOS_MUTEX) */
1218
1219 // Don't call this from interrupt handlers.
1221 // Don't try to lock a non-recursive mutex again.
1222 os_assert_err (!scheduler::locked (), EPERM);
1223
1224 if (!recoverable_)
1225 {
1226 return ENOTRECOVERABLE;
1227 }
1228
1229#if defined(OS_USE_RTOS_PORT_MUTEX)
1230
1231 return port::mutex::timed_lock (this, timeout);
1232
1233#else
1234
1235 thread& crt_thread = this_thread::thread ();
1236
1237 result_t res;
1238
1239 // Extra test before entering the loop, with its inherent weight.
1240 // Trade size for speed.
1241 {
1242 // ----- Enter critical section ---------------------------------------
1243 scheduler::critical_section scs;
1244
1245 res = internal_try_lock_ (&crt_thread);
1246 if (res != EWOULDBLOCK)
1247 {
1248 return res;
1249 }
1250 // ----- Exit critical section ----------------------------------------
1251 }
1252
1253 // Prepare a list node pointing to the current thread.
1254 // Do not worry for being on stack, it is temporarily linked to the
1255 // list and guaranteed to be removed before this function returns.
1256 internal::waiting_thread_node node{ crt_thread };
1257
1258 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
1259 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
1260
1261 // Prepare a timeout node pointing to the current thread.
1262 internal::timeout_thread_node timeout_node{ timeout_timestamp,
1263 crt_thread };
1264
1265 for (;;)
1266 {
1267 {
1268 // ----- Enter critical section -----------------------------------
1269 scheduler::critical_section scs;
1270
1271 res = internal_try_lock_ (&crt_thread);
1272 if (res != EWOULDBLOCK)
1273 {
1274 return res;
1275 }
1276
1277 {
1278 // ----- Enter critical section -----------------------------
1279 interrupts::critical_section ics;
1280
1281 // Add this thread to the mutex waiting list,
1282 // and the clock timeout list.
1283 scheduler::internal_link_node (list_, node, clock_list,
1284 timeout_node);
1285 // state::suspended set in above link().
1286 // ----- Exit critical section ------------------------------
1287 }
1288 // ----- Exit critical section ------------------------------------
1289 }
1290
1292
1293 // Remove the thread from the semaphore waiting list,
1294 // if not already removed by unlock() and from the clock
1295 // timeout list, if not already removed by the timer.
1296 scheduler::internal_unlink_node (node, timeout_node);
1297
1298 res = result::ok;
1299
1300 if (crt_thread.interrupted ())
1301 {
1302#if defined(OS_TRACE_RTOS_MUTEX)
1303 trace::printf ("%s() EINTR @%p %s \n", __func__, this, name ());
1304#endif
1305 res = EINTR;
1306 }
1307 else if (clock_->steady_now () >= timeout_timestamp)
1308 {
1309#if defined(OS_TRACE_RTOS_MUTEX)
1310 trace::printf ("%s() ETIMEDOUT @%p %s \n", __func__, this,
1311 name ());
1312#endif
1313 res = ETIMEDOUT;
1314 }
1315 if (res != result::ok)
1316 {
1317 if (boosted_prio_ != thread::priority::none)
1318 {
1319 // If the priority was boosted, it must be restored
1320 // to the highest priority of the waiting threads, if any.
1321
1323
1324#pragma GCC diagnostic push
1325#if defined(__clang__)
1326#elif defined(__GNUC__)
1327#pragma GCC diagnostic ignored "-Waggregate-return"
1328#endif
1329 for (auto&& th : list_)
1330 {
1331 thread::priority_t prio = th.priority ();
1332 if (prio > max_prio)
1333 {
1334 max_prio = prio;
1335 }
1336 }
1337#pragma GCC diagnostic pop
1338
1339 if (max_prio != thread::priority::none)
1340 {
1341 boosted_prio_ = max_prio;
1342 owner_->priority (boosted_prio_);
1343 }
1344 }
1345 return res;
1346 }
1347 }
1348
1349 /* NOTREACHED */
1350 return ENOTRECOVERABLE;
1351
1352#endif
1353 }
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:88
uint8_t priority_t
Type of variables holding thread priorities.
Definition os-thread.h:271

References os::rtos::interrupts::in_handler_mode(), os::rtos::thread::interrupted(), os::rtos::scheduler::locked(), os::rtos::internal::object_named::name(), os::rtos::thread::priority::none, os::rtos::result::ok, os_assert_err, os::trace::printf(), os::rtos::port::scheduler::reschedule(), and os::rtos::this_thread::thread().

Referenced by os::estd::timed_mutex::try_lock_for(), and os::estd::recursive_timed_mutex::try_lock_for().

◆ try_lock()

result_t os::rtos::mutex::try_lock ( void  )
inherited
Parameters
None.
Return values
result::okThe mutex was locked.
EPERMCannot be invoked from an Interrupt Service Routines.
ENOTRECOVERABLEThe state protected by the mutex is not recoverable..
EAGAINThe mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
EINVALThe 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.
EOWNERDEADThe 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.
EDEADLKThe mutex type is mutex::type::errorcheck and the current thread already owns the mutex.
EWOULDBLOCKThe 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.

POSIX compatibility
Inspired by pthread_mutex_trylock() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Differences from the standard:
  • for consistency reasons, EWOULDBLOCK is used, instead of EBUSY
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1126 of file os-mutex.cpp.

1127 {
1128#if defined(OS_TRACE_RTOS_MUTEX)
1129 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1131#endif
1132
1133 // Don't call this from interrupt handlers.
1135
1136 if (!recoverable_)
1137 {
1138 return ENOTRECOVERABLE;
1139 }
1140
1141#if defined(OS_USE_RTOS_PORT_MUTEX)
1142
1143 return port::mutex::try_lock (this);
1144
1145#else
1146
1147 thread& crt_thread = this_thread::thread ();
1148
1149 {
1150 // ----- Enter critical section ---------------------------------------
1151 scheduler::critical_section scs;
1152
1153 return internal_try_lock_ (&crt_thread);
1154 // ----- Exit critical section ----------------------------------------
1155 }
1156
1157#endif
1158 }

References os::rtos::interrupts::in_handler_mode(), os::rtos::internal::object_named::name(), os_assert_err, os::trace::printf(), and os::rtos::this_thread::thread().

Referenced by os::estd::mutex::try_lock(), and os::estd::recursive_mutex::try_lock().

◆ type()

mutex::type_t os::rtos::mutex::type ( void  )
inlineinherited
Returns
An integer encoding the mutex::type.
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 829 of file os-mutex.h.

830 {
831 return type_;
832 }

◆ unlock()

result_t os::rtos::mutex::unlock ( void  )
inherited
Parameters
None.
Return values
result::okThe mutex was unlocked.
EPERMCannot 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.
ENOTRECOVERABLEThe 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.

POSIX compatibility
Inspired by pthread_mutex_unlock() from <pthread.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 1379 of file os-mutex.cpp.

1380 {
1381#if defined(OS_TRACE_RTOS_MUTEX)
1382 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1384#endif
1385
1386 // Don't call this from interrupt handlers.
1388
1389#if defined(OS_USE_RTOS_PORT_MUTEX)
1390
1391 return port::mutex::unlock (this);
1392
1393#else
1394
1395 thread* crt_thread = &this_thread::thread ();
1396
1397 return internal_unlock_ (crt_thread);
1398
1399#endif
1400 }

References os::rtos::interrupts::in_handler_mode(), os::rtos::internal::object_named::name(), os_assert_err, os::trace::printf(), and os::rtos::this_thread::thread().

Referenced by os::rtos::mutex::prio_ceiling(), os::estd::mutex::unlock(), and os::estd::recursive_mutex::unlock().


The documentation for this class was generated from the following files: