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_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "platform/NonCopyable.h"
#include "platform/ScopedLock.h"
@ -105,9 +106,23 @@ public:
the lock attempt will time out earlier than specified.
@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);
/** 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
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if the mutex was acquired, false otherwise.
@ -117,9 +132,24 @@ public:
the lock attempt will time out earlier than specified.
@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);
/** 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
@ -178,11 +208,21 @@ inline bool Mutex::trylock_for(uint32_t)
return true;
}
inline bool Mutex::trylock_for(Kernel::Clock::duration_u32)
{
return true;
}
inline bool Mutex::trylock_until(uint64_t)
{
return true;
}
inline bool Mutex::trylock_until(Kernel::Clock::time_point)
{
return true;
}
inline void Mutex::unlock()
{
}

View File

@ -29,6 +29,10 @@
#if MBED_CONF_RTOS_PRESENT
using namespace std::chrono_literals;
using std::milli;
using std::chrono::duration;
namespace rtos {
Mutex::Mutex()
@ -71,20 +75,25 @@ void Mutex::lock(void)
bool Mutex::trylock()
{
return trylock_for(0);
return trylock_for(0s);
}
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) {
_count++;
return true;
}
bool success = (status == osOK ||
(status == osErrorResource && millisec == 0) ||
(status == osErrorTimeout && millisec != osWaitForever));
(status == osErrorResource && rel_time == rel_time.zero()) ||
(status == osErrorTimeout && rel_time <= Kernel::wait_for_u32_max));
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);
@ -95,15 +104,20 @@ bool Mutex::trylock_for(uint32_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();
} else if (millisec - now >= osWaitForever) {
} else if (abs_time - now > Kernel::wait_for_u32_max) {
// API permits early return
return trylock_for(osWaitForever - 1);
return trylock_for(Kernel::wait_for_u32_max);
} else {
return trylock_for(millisec - now);
return trylock_for(abs_time - now);
}
}