Add Chrono support to Semaphore

pull/12425/head
Kevin Bracey 2020-02-12 16:12:56 +02:00
parent 0223d92f7e
commit 53cfe0f610
2 changed files with 53 additions and 12 deletions

View File

@ -24,9 +24,11 @@
#define SEMAPHORE_H
#include <stdint.h>
#include <chrono>
#include "rtos/mbed_rtos_types.h"
#include "rtos/mbed_rtos1_types.h"
#include "rtos/mbed_rtos_storage.h"
#include "rtos/Kernel.h"
#include "platform/mbed_toolchain.h"
#include "platform/NonCopyable.h"
@ -81,9 +83,34 @@ public:
@return true if a resource was acquired, false otherwise.
@note You may call this function from ISR context if the millisec parameter is set to 0.
@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 try_acquire_for(uint32_t millisec);
/** Wait until a Semaphore resource becomes available.
@param rel_time timeout value.
@return true if a resource was acquired, false otherwise.
@note You may call this function from ISR context if the rel_time parameter is set to 0.
*/
bool try_acquire_for(Kernel::Clock::duration_u32 rel_time);
/** Wait until a Semaphore resource becomes available.
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if a resource 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 acquire 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 try_acquire_until(uint64_t millisec);
/** Wait until a Semaphore resource becomes available.
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@return true if a resource was acquired, false otherwise.
@ -94,7 +121,7 @@ public:
@note You cannot call this function from ISR context.
*/
bool try_acquire_until(uint64_t millisec);
bool try_acquire_until(Kernel::Clock::time_point abs_time);
/** Release a Semaphore resource that was obtain with Semaphore::acquire.
@return status code that indicates the execution status of the function:

View File

@ -29,6 +29,10 @@
#include <string.h>
using namespace std::chrono_literals;
using std::chrono::duration;
using std::milli;
namespace rtos {
Semaphore::Semaphore(int32_t count)
@ -104,15 +108,20 @@ void Semaphore::acquire()
}
bool Semaphore::try_acquire_for(uint32_t millisec)
{
return try_acquire_for(duration<uint32_t, milli>(millisec));
}
bool Semaphore::try_acquire_for(Kernel::Clock::duration_u32 rel_time)
{
#if MBED_CONF_RTOS_PRESENT
osStatus_t status = osSemaphoreAcquire(_id, millisec);
osStatus_t status = osSemaphoreAcquire(_id, rel_time.count());
if (status == osOK) {
return true;
}
bool success = (status == osErrorResource && millisec == 0) ||
(status == osErrorTimeout && millisec != osWaitForever);
bool success = (status == osErrorResource && rel_time == rel_time.zero()) ||
(status == osErrorTimeout);
if (!success) {
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status);
@ -120,27 +129,32 @@ bool Semaphore::try_acquire_for(uint32_t millisec)
return false;
#else
sem_wait_capture capture = { this, false };
mbed::internal::do_timed_sleep_relative_or_forever(millisec, semaphore_available, &capture);
mbed::internal::do_timed_sleep_relative_or_forever(rel_time, semaphore_available, &capture);
return capture.acquired;
#endif
}
bool Semaphore::try_acquire_until(uint64_t millisec)
{
#if MBED_CONF_RTOS_PRESENT
uint64_t now = Kernel::get_ms_count();
return try_acquire_until(Kernel::Clock::time_point(duration<uint64_t, milli>(millisec)));
}
if (now >= millisec) {
bool Semaphore::try_acquire_until(Kernel::Clock::time_point abs_time)
{
#if MBED_CONF_RTOS_PRESENT
Kernel::Clock::time_point now = Kernel::Clock::now();
if (now >= abs_time) {
return try_acquire();
} else if (millisec - now >= osWaitForever) {
} else if (abs_time - now > Kernel::wait_for_u32_max) {
// API permits early return
return try_acquire_for(osWaitForever - 1);
return try_acquire_for(Kernel::wait_for_u32_max);
} else {
return try_acquire_for(millisec - now);
return try_acquire_for(abs_time - now);
}
#else
sem_wait_capture capture = { this, false };
mbed::internal::do_timed_sleep_absolute(millisec, semaphore_available, &capture);
mbed::internal::do_timed_sleep_absolute(abs_time, semaphore_available, &capture);
return capture.acquired;
#endif
}