add timeout_us/until to mutex/sem blocking methods (#402)

This commit is contained in:
Graham Sanderson 2021-05-12 16:32:45 -05:00 committed by GitHub
parent 54c78bf985
commit c6c4eeb122
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 6 deletions

View File

@ -91,6 +91,20 @@ bool mutex_try_enter(mutex_t *mtx, uint32_t *owner_out);
*/ */
bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms); bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms);
/*! \brief Wait for mutex with timeout
* \ingroup mutex
*
* Wait for up to the specific time to take ownership of the mutex. If the calling
* core can take ownership of the mutex before the timeout expires, then true will be returned
* and the calling core will own the mutex, otherwise false will be returned and the calling
* core will *NOT* own the mutex.
*
* \param mtx Pointer to mutex structure
* \param timeout_us The timeout in microseconds.
* \return true if mutex now owned, false if timeout occurred before mutex became available
*/
bool mutex_enter_timeout_us(mutex_t *mtx, uint32_t timeout_us);
/*! \brief Wait for mutex until a specific time /*! \brief Wait for mutex until a specific time
* \ingroup mutex * \ingroup mutex
* *

View File

@ -90,11 +90,38 @@ void sem_acquire_blocking(semaphore_t *sem);
* return false, otherwise it will return true. * return false, otherwise it will return true.
* *
* \param sem Pointer to semaphore structure * \param sem Pointer to semaphore structure
* \param timeout_ms Time to wait to acquire the semaphore, in ms. * \param timeout_ms Time to wait to acquire the semaphore, in milliseconds.
* \return false if timeout reached, true if permit was acquired. * \return false if timeout reached, true if permit was acquired.
*/ */
bool sem_acquire_timeout_ms(semaphore_t *sem, uint32_t timeout_ms); bool sem_acquire_timeout_ms(semaphore_t *sem, uint32_t timeout_ms);
/*! \brief Acquire a permit from a semaphore, with timeout
* \ingroup sem
*
* This function will block and wait if no permits are available, until the
* defined timeout has been reached. If the timeout is reached the function will
* return false, otherwise it will return true.
*
* \param sem Pointer to semaphore structure
* \param timeout_us Time to wait to acquire the semaphore, in microseconds.
* \return false if timeout reached, true if permit was acquired.
*/
bool sem_acquire_timeout_us(semaphore_t *sem, uint32_t timeout_us);
/*! \brief Wait to acquire a permit from a semaphore until a specific time
* \ingroup sem
*
* This function will block and wait if no permits are available, until the
* specified timeout time. If the timeout is reached the function will
* return false, otherwise it will return true.
*
* \param sem Pointer to semaphore structure
* \param until The time after which to return if the sem is not available.
* \return true if permit was acquired, false if the until time was reached before
* acquiring.
*/
bool sem_acquire_until(semaphore_t *sem, absolute_time_t until);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -67,6 +67,10 @@ bool __time_critical_func(mutex_enter_timeout_ms)(mutex_t *mtx, uint32_t timeout
return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms)); return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
} }
bool __time_critical_func(mutex_enter_timeout_us)(mutex_t *mtx, uint32_t timeout_us) {
return mutex_enter_block_until(mtx, make_timeout_time_us(timeout_us));
}
bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) { bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
assert(mtx->core.spin_lock); assert(mtx->core.spin_lock);
do { do {

View File

@ -31,7 +31,14 @@ void __time_critical_func(sem_acquire_blocking)(semaphore_t *sem) {
} }
bool __time_critical_func(sem_acquire_timeout_ms)(semaphore_t *sem, uint32_t timeout_ms) { bool __time_critical_func(sem_acquire_timeout_ms)(semaphore_t *sem, uint32_t timeout_ms) {
absolute_time_t target = nil_time; return sem_acquire_until(sem, make_timeout_time_ms(timeout_ms));
}
bool __time_critical_func(sem_acquire_timeout_us)(semaphore_t *sem, uint32_t timeout_us) {
return sem_acquire_until(sem, make_timeout_time_us(timeout_us));
}
bool __time_critical_func(sem_acquire_until)(semaphore_t *sem, absolute_time_t until) {
do { do {
uint32_t save = spin_lock_blocking(sem->core.spin_lock); uint32_t save = spin_lock_blocking(sem->core.spin_lock);
if (sem->permits > 0) { if (sem->permits > 0) {
@ -39,10 +46,7 @@ bool __time_critical_func(sem_acquire_timeout_ms)(semaphore_t *sem, uint32_t tim
lock_internal_spin_unlock_with_notify(&sem->core, save); lock_internal_spin_unlock_with_notify(&sem->core, save);
return true; return true;
} }
if (is_nil_time(target)) { if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&sem->core, save, until)) {
target = make_timeout_time_ms(timeout_ms);
}
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&sem->core, save, target)) {
return false; return false;
} }
} while (true); } while (true);