Add Chrono support to Mutex

pull/12425/head
Kevin Bracey 2020-02-12 16:18:18 +02:00
parent 53cfe0f610
commit 2c4e59012f
2 changed files with 63 additions and 9 deletions

View File

@ -27,6 +27,7 @@
#include "rtos/mbed_rtos_types.h" #include "rtos/mbed_rtos_types.h"
#include "rtos/mbed_rtos1_types.h" #include "rtos/mbed_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h" #include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "platform/NonCopyable.h" #include "platform/NonCopyable.h"
#include "platform/ScopedLock.h" #include "platform/ScopedLock.h"
@ -105,9 +106,23 @@ public:
the lock attempt will time out earlier than specified. the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context. @note You cannot call this function from ISR context.
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
*/ */
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
bool trylock_for(uint32_t millisec); bool trylock_for(uint32_t millisec);
/** Try to lock the mutex for a specified time
@param rel_time timeout value.
@return true if the mutex was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
*/
bool trylock_for(Kernel::Clock::duration_u32 rel_time);
/** Try to lock the mutex until specified time /** Try to lock the mutex until specified time
@param millisec absolute timeout time, referenced to Kernel::get_ms_count() @param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if the mutex was acquired, false otherwise. @return true if the mutex was acquired, false otherwise.
@ -117,9 +132,24 @@ public:
the lock attempt will time out earlier than specified. the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context. @note You cannot call this function from ISR context.
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use
`Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.
*/ */
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
bool trylock_until(uint64_t millisec); bool trylock_until(uint64_t millisec);
/** Try to lock the mutex until specified time
@param abs_time absolute timeout time, referenced to Kernel::get_ms_count()
@return true if the mutex was acquired, false otherwise.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the lock attempt will time out earlier than specified.
@note You cannot call this function from ISR context.
*/
bool trylock_until(Kernel::Clock::time_point abs_time);
/** /**
Unlock the mutex that has previously been locked by the same thread Unlock the mutex that has previously been locked by the same thread
@ -178,11 +208,21 @@ inline bool Mutex::trylock_for(uint32_t)
return true; return true;
} }
inline bool Mutex::trylock_for(Kernel::Clock::duration_u32)
{
return true;
}
inline bool Mutex::trylock_until(uint64_t) inline bool Mutex::trylock_until(uint64_t)
{ {
return true; return true;
} }
inline bool Mutex::trylock_until(Kernel::Clock::time_point)
{
return true;
}
inline void Mutex::unlock() inline void Mutex::unlock()
{ {
} }

View File

@ -29,6 +29,10 @@
#if MBED_CONF_RTOS_PRESENT #if MBED_CONF_RTOS_PRESENT
using namespace std::chrono_literals;
using std::milli;
using std::chrono::duration;
namespace rtos { namespace rtos {
Mutex::Mutex() Mutex::Mutex()
@ -71,20 +75,25 @@ void Mutex::lock(void)
bool Mutex::trylock() bool Mutex::trylock()
{ {
return trylock_for(0); return trylock_for(0s);
} }
bool Mutex::trylock_for(uint32_t millisec) bool Mutex::trylock_for(uint32_t millisec)
{ {
osStatus status = osMutexAcquire(_id, millisec); return trylock_for(duration<uint32_t, milli>(millisec));
}
bool Mutex::trylock_for(Kernel::Clock::duration_u32 rel_time)
{
osStatus status = osMutexAcquire(_id, rel_time.count());
if (status == osOK) { if (status == osOK) {
_count++; _count++;
return true; return true;
} }
bool success = (status == osOK || bool success = (status == osOK ||
(status == osErrorResource && millisec == 0) || (status == osErrorResource && rel_time == rel_time.zero()) ||
(status == osErrorTimeout && millisec != osWaitForever)); (status == osErrorTimeout && rel_time <= Kernel::wait_for_u32_max));
if (!success && !mbed_get_error_in_progress()) { if (!success && !mbed_get_error_in_progress()) {
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status); MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
@ -95,15 +104,20 @@ bool Mutex::trylock_for(uint32_t millisec)
bool Mutex::trylock_until(uint64_t millisec) bool Mutex::trylock_until(uint64_t millisec)
{ {
uint64_t now = Kernel::get_ms_count(); return trylock_until(Kernel::Clock::time_point(duration<uint64_t, milli>(millisec)));
}
if (now >= millisec) { bool Mutex::trylock_until(Kernel::Clock::time_point abs_time)
{
Kernel::Clock::time_point now = Kernel::Clock::now();
if (now >= abs_time) {
return trylock(); return trylock();
} else if (millisec - now >= osWaitForever) { } else if (abs_time - now > Kernel::wait_for_u32_max) {
// API permits early return // API permits early return
return trylock_for(osWaitForever - 1); return trylock_for(Kernel::wait_for_u32_max);
} else { } else {
return trylock_for(millisec - now); return trylock_for(abs_time - now);
} }
} }