From ffec6124f29f982d268571d24733b9f9d56f38a9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 1 Aug 2015 14:57:31 -0600 Subject: [PATCH] Add a start time to sem_tickwait() to account for any elapsed time before the timer is actually started --- include/nuttx/semaphore.h | 11 ++++++++--- sched/semaphore/sem_tickwait.c | 29 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index a7ed6d58043..5460ce15c5a 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -94,8 +94,13 @@ extern "C" * * Parameters: * sem - Semaphore object - * ticks - Ticks to wait until the semaphore is posted. If ticks is - * zero, then this function is equivalent to sem_trywait(). + * start - The system time that the delay is relative to. If the + * current time is not the same as the start time, then the + * delay will be adjust so that the end time will be the same + * in any event. + * delay - Ticks to wait from the start time until the semaphore is + * posted. If ticks is zero, then this function is equivalent + * to sem_trywait(). * * Return Value: * Zero (OK) is returned on success. A negated errno value is returned on @@ -103,7 +108,7 @@ extern "C" * ****************************************************************************/ -int sem_tickwait(FAR sem_t *sem, uint32_t ticks); +int sem_tickwait(FAR sem_t *sem, uint32_t start, uint32_t delay); #undef EXTERN #ifdef __cplusplus diff --git a/sched/semaphore/sem_tickwait.c b/sched/semaphore/sem_tickwait.c index 92942d555a9..8d742a17300 100644 --- a/sched/semaphore/sem_tickwait.c +++ b/sched/semaphore/sem_tickwait.c @@ -47,6 +47,7 @@ #include #include +#include #include #include "sched/sched.h" @@ -65,19 +66,25 @@ * * Parameters: * sem - Semaphore object - * ticks - Ticks to wait until the semaphore is posted. If ticks is - * zero, then this function is equivalent to sem_trywait(). + * start - The system time that the delay is relative to. If the + * current time is not the same as the start time, then the + * delay will be adjust so that the end time will be the same + * in any event. + * delay - Ticks to wait from the start time until the semaphore is + * posted. If ticks is zero, then this function is equivalent + * to sem_trywait(). * * Return Value: - * Zero (OK) is returned on success. A negated errno value is retuend on + * Zero (OK) is returned on success. A negated errno value is returned on * failure. -ETIMEDOUT is returned on the timeout condition. * ****************************************************************************/ -int sem_tickwait(FAR sem_t *sem, uint32_t ticks) +int sem_tickwait(FAR sem_t *sem, uint32_t start, uint32_t delay) { FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; irqstate_t flags; + uint32_t elapsed; int ret; DEBUGASSERT(sem |= NULL && up_interrupt_context() == false && @@ -118,7 +125,7 @@ int sem_tickwait(FAR sem_t *sem, uint32_t ticks) * with a valid timeout. */ - if (ticks == 0) + if (delay == 0) { /* Return the errno from sem_trywait() */ @@ -126,9 +133,19 @@ int sem_tickwait(FAR sem_t *sem, uint32_t ticks) goto errout_with_irqdisabled; } + /* Adjust the delay for any time since the delay was calculated */ + + elapsed = clock_systimer() - start; + if (elapsed >= (UINT32_MAX / 2) || elapsed >= delay) + { + return -ETIMEDOUT; + } + + delay -= elapsed; + /* Start the watchdog with interrupts still disabled */ - (void)wd_start(rtcb->waitdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); + (void)wd_start(rtcb->waitdog, delay, (wdentry_t)sem_timeout, 1, getpid()); /* Now perform the blocking wait */