Add ConditionVariable::wait_until

Given the 64-bit timebase, add wait_until to ConditionVariable.

Move the timeout example to wait_until(), and give wait_for() an
alternative example, as it's no longer the best option for a
timeout.

Tidy up - remove the redundant RESUME_SIGNAL definition.
pull/5419/head
Kevin Bracey 2017-11-10 15:01:51 +02:00
parent 3bb2c445ca
commit bbefeb4432
2 changed files with 57 additions and 9 deletions

View File

@ -20,6 +20,7 @@
* SOFTWARE.
*/
#include "rtos/ConditionVariable.h"
#include "rtos/Kernel.h"
#include "rtos/Thread.h"
#include "mbed_error.h"
@ -27,7 +28,6 @@
namespace rtos {
ConditionVariable::Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false)
{
// No initialization to do
@ -64,6 +64,24 @@ bool ConditionVariable::wait_for(uint32_t millisec)
return timeout;
}
bool ConditionVariable::wait_until(uint64_t millisec)
{
uint64_t now = Kernel::get_ms_count();
if (now >= millisec) {
// Time has already passed - standard behaviour is to
// treat as a "try".
return wait_for(0);
} else if (millisec - now >= osWaitForever) {
// Exceeds maximum delay of underlying wait_for -
// spuriously wake after 49 days, indicating no timeout.
wait_for(osWaitForever - 1);
return false;
} else {
return wait_for(millisec - now);
}
}
void ConditionVariable::notify_one()
{
MBED_ASSERT(_mutex.get_owner() == Thread::gettid());

View File

@ -150,6 +150,39 @@ public:
*/
void wait();
/** Wait for a notification until specified time
*
* @param millisec absolute end time referenced to Kernel::get_ms_count()
* @return true if a timeout occurred, false otherwise.
*
* @note - The thread calling this function must be the owner of the
* ConditionVariable's mutex and it must be locked exactly once
* @note - Spurious notifications can occur so the caller of this API
* should check to make sure the condition they are waiting on has
* been met
*
* Example:
* @code
* mutex.lock();
* uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT;
*
* while (!condition_met) {
* if (cond.wait_until(end_time)) {
* break;
* }
* }
*
* if (condition_met) {
* function_to_handle_condition();
* }
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
bool wait_until(uint64_t millisec);
/** Wait for a notification or timeout
*
* @param millisec timeout value or osWaitForever in case of no time-out.
@ -164,15 +197,12 @@ public:
* Example:
* @code
* mutex.lock();
* Timer timer;
* timer.start();
*
* bool timed_out = false;
* uint32_t time_left = TIMEOUT;
* while (!condition_met && !timed_out) {
* timed_out = cond.wait_for(time_left);
* uint32_t elapsed = timer.read_ms();
* time_left = elapsed > TIMEOUT ? 0 : TIMEOUT - elapsed;
* while (!condition_met) {
* cond.wait_for(MAX_SLEEP_TIME);
* if (!condition_met) {
* do_other_work_while_condition_false();
* }
* }
*
* if (condition_met) {