diff --git a/arch/arm/src/efm32/efm32_i2c.c b/arch/arm/src/efm32/efm32_i2c.c index 40c4bcf9d0..bb85170c8b 100644 --- a/arch/arm/src/efm32/efm32_i2c.c +++ b/arch/arm/src/efm32/efm32_i2c.c @@ -578,16 +578,16 @@ static inline int efm32_i2c_sem_waitdone(FAR struct efm32_i2c_priv_s *priv) /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); + ret = nxsem_timedwait(&priv->sem_isr, &abstime); /* Disable I2C interrupts */ efm32_i2c_putreg(priv, EFM32_I2C_IEN_OFFSET, 0); - if (ret != OK && errno != EINTR) + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would include - * timeouts and mystery errors reported by sem_timedwait. NOTE that + * timeouts and mystery errors reported by nxsem_timedwait. NOTE that * we try again if we are awakened by a signal (EINTR). */ @@ -624,7 +624,7 @@ static inline int efm32_i2c_sem_waitdone(FAR struct efm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts are * currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ start = clock_systimer(); diff --git a/arch/arm/src/lc823450/lc823450_i2c.c b/arch/arm/src/lc823450/lc823450_i2c.c index 5c1569388b..fdda0e4690 100644 --- a/arch/arm/src/lc823450/lc823450_i2c.c +++ b/arch/arm/src/lc823450/lc823450_i2c.c @@ -54,9 +54,10 @@ #include #include -#include #include #include +#include +#include #include @@ -308,11 +309,7 @@ static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv { /* Get the current time */ -#ifdef CONFIG_CLOCK_MONOTONIC - (void)clock_gettime(CLOCK_MONOTONIC, &abstime); -#else (void)clock_gettime(CLOCK_REALTIME, &abstime); -#endif /* Calculate a time in the future */ @@ -331,16 +328,12 @@ static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv /* Wait until either the transfer is complete or the timeout expires */ -#ifdef CONFIG_CLOCK_MONOTONIC - ret = sem_timedwait_monotonic(&priv->sem_isr, &abstime); -#else - ret = sem_timedwait(&priv->sem_isr, &abstime); -#endif - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && errno != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ break; diff --git a/arch/arm/src/samdl/sam_i2c_master.c b/arch/arm/src/samdl/sam_i2c_master.c index 34999af681..01fb92a1cf 100644 --- a/arch/arm/src/samdl/sam_i2c_master.c +++ b/arch/arm/src/samdl/sam_i2c_master.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -624,15 +625,16 @@ static inline void i2c_putrel(struct sam_i2c_dev_s *priv, unsigned int offset, static int i2c_wait_for_bus(struct sam_i2c_dev_s *priv, unsigned int size) { struct timespec ts; + int ret; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_nsec += 200e3; - if (sem_timedwait(&priv->waitsem, (const struct timespec *)&ts) != OK) + ret = nxsem_timedwait(&priv->waitsem, (const struct timespec *)&ts); + if (ret < 0) { - int errcode = errno; - i2cinfo("timedwait error %d\n", errcode); - return -errcode; + i2cinfo("timedwait error %d\n", ret); + return ret; } return priv->result; diff --git a/arch/arm/src/stm32/stm32_1wire.c b/arch/arm/src/stm32/stm32_1wire.c index a917348f9e..a4157006a6 100644 --- a/arch/arm/src/stm32/stm32_1wire.c +++ b/arch/arm/src/stm32/stm32_1wire.c @@ -814,11 +814,11 @@ static int stm32_1wire_process(struct stm32_1wire_priv_s *priv, stm32_1wire_send(priv, RESET_TX); leave_critical_section(irqs); - /* Wait */ + /* Wait. Break on timeout if TX line closed to GND */ clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += BUS_TIMEOUT; - sem_timedwait(&priv->sem_isr, &abstime); /* break on timeout if TX line closed to GND */ + (void)nxsem_timedwait(&priv->sem_isr, &abstime); break; case ONEWIRETASK_WRITE: @@ -836,11 +836,11 @@ static int stm32_1wire_process(struct stm32_1wire_priv_s *priv, stm32_1wire_send(priv, (*priv->byte & (1 << priv->bit)) ? WRITE_TX1 : WRITE_TX0); leave_critical_section(irqs); - /* Wait */ + /* Wait. Break on timeout if TX line closed to GND */ clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += BUS_TIMEOUT; - sem_timedwait(&priv->sem_isr, &abstime); /* break on timeout if TX line closed to GND */ + (void)nxsem_timedwait(&priv->sem_isr, &abstime); break; case ONEWIRETASK_READ: @@ -858,11 +858,11 @@ static int stm32_1wire_process(struct stm32_1wire_priv_s *priv, stm32_1wire_send(priv, READ_TX); leave_critical_section(irqs); - /* Wait */ + /* Wait. Break on timeout if TX line closed to GND */ clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += BUS_TIMEOUT; - sem_timedwait(&priv->sem_isr, &abstime); /* break on timeout if TX line closed to GND */ + (void)nxsem_timedwait(&priv->sem_isr, &abstime); break; } diff --git a/arch/arm/src/stm32/stm32_i2c.c b/arch/arm/src/stm32/stm32_i2c.c index 87c783f2ca..00f9139500 100644 --- a/arch/arm/src/stm32/stm32_i2c.c +++ b/arch/arm/src/stm32/stm32_i2c.c @@ -577,7 +577,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; @@ -614,11 +614,11 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -661,7 +661,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/stm32/stm32_i2c_alt.c b/arch/arm/src/stm32/stm32_i2c_alt.c index b772363a9d..18dde6c80c 100644 --- a/arch/arm/src/stm32/stm32_i2c_alt.c +++ b/arch/arm/src/stm32/stm32_i2c_alt.c @@ -585,7 +585,7 @@ static int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; @@ -622,11 +622,11 @@ static int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -669,7 +669,7 @@ static int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/stm32/stm32f30xxx_i2c.c b/arch/arm/src/stm32/stm32f30xxx_i2c.c index 7a1fad370a..371d749d0d 100644 --- a/arch/arm/src/stm32/stm32f30xxx_i2c.c +++ b/arch/arm/src/stm32/stm32f30xxx_i2c.c @@ -614,7 +614,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; @@ -650,11 +650,11 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) #endif /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -695,7 +695,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/stm32/stm32f40xxx_i2c.c b/arch/arm/src/stm32/stm32f40xxx_i2c.c index 195c9cc596..86de66e7f5 100644 --- a/arch/arm/src/stm32/stm32f40xxx_i2c.c +++ b/arch/arm/src/stm32/stm32f40xxx_i2c.c @@ -633,7 +633,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; @@ -670,11 +670,11 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -717,7 +717,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/stm32f0/stm32f0_i2c.c b/arch/arm/src/stm32f0/stm32f0_i2c.c index 8e83bedf79..3ae93e42ad 100644 --- a/arch/arm/src/stm32f0/stm32f0_i2c.c +++ b/arch/arm/src/stm32f0/stm32f0_i2c.c @@ -556,7 +556,7 @@ static inline int stm32f0_i2c_sem_waitdone(FAR struct stm32f0_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; @@ -592,11 +592,11 @@ static inline int stm32f0_i2c_sem_waitdone(FAR struct stm32f0_i2c_priv_s *priv) #endif /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -637,7 +637,7 @@ static inline int stm32f0_i2c_sem_waitdone(FAR struct stm32f0_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/stm32f7/stm32_i2c.c b/arch/arm/src/stm32f7/stm32_i2c.c index 09f7bdcefa..7d86a4dff7 100644 --- a/arch/arm/src/stm32f7/stm32_i2c.c +++ b/arch/arm/src/stm32f7/stm32_i2c.c @@ -839,11 +839,11 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) #endif /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -884,7 +884,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/stm32l4/stm32l4_i2c.c b/arch/arm/src/stm32l4/stm32l4_i2c.c index 1f46b166e5..28b15b2aa1 100644 --- a/arch/arm/src/stm32l4/stm32l4_i2c.c +++ b/arch/arm/src/stm32l4/stm32l4_i2c.c @@ -588,7 +588,7 @@ static inline int stm32l4_i2c_sem_waitdone(FAR struct stm32l4_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; @@ -624,11 +624,11 @@ static inline int stm32l4_i2c_sem_waitdone(FAR struct stm32l4_i2c_priv_s *priv) #endif /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->sem_isr, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->sem_isr, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -669,7 +669,7 @@ static inline int stm32l4_i2c_sem_waitdone(FAR struct stm32l4_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ priv->intstate = INTSTATE_WAITING; diff --git a/arch/arm/src/tiva/tiva_i2c.c b/arch/arm/src/tiva/tiva_i2c.c index 511f12fa07..aee4501051 100644 --- a/arch/arm/src/tiva/tiva_i2c.c +++ b/arch/arm/src/tiva/tiva_i2c.c @@ -718,7 +718,7 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ do @@ -754,11 +754,11 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) /* Wait until either the transfer is complete or the timeout expires */ - ret = sem_timedwait(&priv->waitsem, &abstime); - if (ret != OK && errno != EINTR) + ret = nxsem_timedwait(&priv->waitsem, &abstime); + if (ret < 0 && ret != -EINTR) { /* Break out of the loop on irrecoverable errors. This would - * include timeouts and mystery errors reported by sem_timedwait. + * include timeouts and mystery errors reported by nxsem_timedwait. * NOTE that we try again if we are awakened by a signal (EINTR). */ @@ -802,7 +802,7 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when - * sem_timedwait() sleeps. + * nxsem_timedwait() sleeps. */ start = clock_systimer(); diff --git a/drivers/contactless/pn532.c b/drivers/contactless/pn532.c index 83acfa35f8..fe8dbd7061 100644 --- a/drivers/contactless/pn532.c +++ b/drivers/contactless/pn532.c @@ -327,7 +327,7 @@ static int pn532_wait_rx_ready(struct pn532_dev_s *dev, int timeout) struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 1; - sem_timedwait(dev->sem_rx, &ts); + (void)nxsem_timedwait(dev->sem_rx, &ts); #endif /* TODO: Handle Exception bits 2, 3 */ diff --git a/drivers/sensors/lps25h.c b/drivers/sensors/lps25h.c index a173ae497d..609e01c74d 100644 --- a/drivers/sensors/lps25h.c +++ b/drivers/sensors/lps25h.c @@ -570,14 +570,13 @@ static int lps25h_one_shot(FAR struct lps25h_dev_s *dev) abstime.tv_nsec -= 1000 * 1000 * 1000; } - while ((ret = sem_timedwait(&dev->waitsem, &abstime)) != 0) + while ((ret = nxsem_timedwait(&dev->waitsem, &abstime)) < 0) { - int err = errno; - if (err == EINTR) + if (ret == -EINTR) { continue; } - else if (err == ETIMEDOUT) + else if (ret == -ETIMEDOUT) { uint8_t reg = LPS25H_CTRL_REG2; uint8_t value; @@ -609,7 +608,7 @@ static int lps25h_one_shot(FAR struct lps25h_dev_s *dev) /* Some unknown mystery error */ DEBUGASSERT(false); - return -err; + return ret; } } diff --git a/drivers/wireless/ieee80211/bcmf_cdc.c b/drivers/wireless/ieee80211/bcmf_cdc.c index 7c540cdc82..463f0c4d18 100644 --- a/drivers/wireless/ieee80211/bcmf_cdc.c +++ b/drivers/wireless/ieee80211/bcmf_cdc.c @@ -227,7 +227,7 @@ int bcmf_cdc_control_request_unsafe(FAR struct bcmf_dev_s *priv, } ret = bcmf_sem_wait(&priv->control_timeout, BCMF_CONTROL_TIMEOUT_MS); - if (ret != OK) + if (ret < 0) { wlerr("Error while waiting for control response %d\n", ret); return ret; diff --git a/drivers/wireless/ieee80211/bcmf_driver.c b/drivers/wireless/ieee80211/bcmf_driver.c index 02465428dc..1a3ae7f76e 100644 --- a/drivers/wireless/ieee80211/bcmf_driver.c +++ b/drivers/wireless/ieee80211/bcmf_driver.c @@ -1188,10 +1188,10 @@ int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr) wlinfo("semwait done ! %d\n", ret); - if (ret) + if (ret < 0) { wlerr("Associate request timeout\n"); - return -EINVAL; + return ret; } switch (priv->auth_status) @@ -1204,5 +1204,6 @@ int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr) wlerr("AP join failed %d\n", priv->auth_status); return -EINVAL; } + return OK; } diff --git a/drivers/wireless/ieee80211/bcmf_utils.c b/drivers/wireless/ieee80211/bcmf_utils.c index 16c42d27ac..62af670a68 100644 --- a/drivers/wireless/ieee80211/bcmf_utils.c +++ b/drivers/wireless/ieee80211/bcmf_utils.c @@ -45,6 +45,8 @@ #include #include +#include + #include "bcmf_utils.h" /**************************************************************************** @@ -117,7 +119,7 @@ int bcmf_sem_wait(sem_t *sem, unsigned int timeout_ms) abstime.tv_nsec -= 1000 * 1000 * 1000; } - return sem_timedwait(sem, &abstime); + return nxsem_timedwait(sem, &abstime); } void bcmf_dqueue_push(dq_queue_t *queue, dq_entry_t *entry) diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index 692d3e386d..069abd1427 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -180,6 +180,52 @@ int nxsem_destroy (FAR sem_t *sem); int nxsem_wait(FAR sem_t *sem); +/**************************************************************************** + * Name: nxsem_timedwait + * + * Description: + * This function will lock the semaphore referenced by sem as in the + * sem_wait() function. However, if the semaphore cannot be locked without + * waiting for another process or thread to unlock the semaphore by + * performing a sem_post() function, this wait will be terminated when the + * specified timeout expires. + * + * The timeout will expire when the absolute time specified by abstime + * passes, as measured by the clock on which timeouts are based (that is, + * when the value of that clock equals or exceeds abstime), or if the + * absolute time specified by abstime has already been passed at the + * time of the call. + * + * This is an internal OS interface. It is functionally equivalent to + * sem_wait except that: + * + * - It is not a cancellaction point, and + * - It does not modify the errno value. + * + * Parameters: + * sem - Semaphore object + * abstime - The absolute time to wait until a timeout is declared. + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * That may be one of: + * + * EINVAL The sem argument does not refer to a valid semaphore. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The semaphore could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * EINTR A signal interrupted this function. + * + ****************************************************************************/ + +struct timespec; /* Forward reference */ +int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime); + /**************************************************************************** * Name: nxsem_tickwait * diff --git a/net/utils/net_lock.c b/net/utils/net_lock.c index 6434dcc2c4..fff004bd3f 100644 --- a/net/utils/net_lock.c +++ b/net/utils/net_lock.c @@ -47,6 +47,7 @@ #include #include +#include #include #include "utils/utils.h" @@ -226,11 +227,11 @@ int net_timedwait(sem_t *sem, FAR const struct timespec *abstime) /* Now take the semaphore, waiting if so requested. */ - if (abstime) + if (abstime != NULL) { /* Wait until we get the lock or until the timeout expires */ - ret = sem_timedwait(sem, abstime); + ret = nxsem_timedwait(sem, abstime); } else { @@ -250,7 +251,6 @@ int net_timedwait(sem_t *sem, FAR const struct timespec *abstime) ret = nxsem_wait(sem); } - sched_unlock(); leave_critical_section(flags); return ret; diff --git a/sched/semaphore/sem_timedwait.c b/sched/semaphore/sem_timedwait.c index 6d19a77e08..b533aa8dc1 100644 --- a/sched/semaphore/sem_timedwait.c +++ b/sched/semaphore/sem_timedwait.c @@ -60,7 +60,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: sem_timedwait + * Name: nxsem_timedwait * * Description: * This function will lock the semaphore referenced by sem as in the @@ -75,13 +75,21 @@ * absolute time specified by abstime has already been passed at the * time of the call. * + * This is an internal OS interface. It is functionally equivalent to + * sem_wait except that: + * + * - It is not a cancellaction point, and + * - It does not modify the errno value. + * * Parameters: - * sem - Semaphore object + * sem - Semaphore object * abstime - The absolute time to wait until a timeout is declared. * * Return Value: - * Zero (OK) is returned on success. On failure, -1 (ERROR) is returned - * and the errno is set appropriately: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * That may be one of: * * EINVAL The sem argument does not refer to a valid semaphore. Or the * thread would have blocked, and the abstime parameter specified @@ -94,20 +102,16 @@ * ****************************************************************************/ -int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) +int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; ssystime_t ticks; - int errcode; - int ret = ERROR; + int status; + int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); - /* sem_timedwait() is a cancellation point */ - - (void)enter_cancellation_point(); - /* Verify the input parameters and, in case of an error, set * errno appropriately. */ @@ -115,8 +119,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) #ifdef CONFIG_DEBUG_FEATURES if (!abstime || !sem) { - errcode = EINVAL; - goto errout; + return -EINVAL; } #endif @@ -128,8 +131,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { - errcode = ENOMEM; - goto errout; + return -ENOMEM; } /* We will disable interrupts until we have completed the semaphore @@ -158,28 +160,32 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { - errcode = EINVAL; + ret = -EINVAL; goto errout_with_irqdisabled; } /* Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. + * + * clock_abstime2ticks() returns zero on success or a POSITIVE errno + * value on failure. */ - errcode = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + status = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired return immediately. */ - if (errcode == OK && ticks <= 0) + if (status == OK && ticks <= 0) { - errcode = ETIMEDOUT; + ret = -ETIMEDOUT; goto errout_with_irqdisabled; } /* Handle any time-related errors */ - if (errcode != OK) + if (status != OK) { + ret = -status; goto errout_with_irqdisabled; } @@ -188,7 +194,9 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) (void)wd_start(rtcb->waitdog, ticks, (wdentry_t)nxsem_timeout, 1, getpid()); - /* Now perform the blocking wait */ + /* Now perform the blocking wait. If nxsem_wait() fails, the + * negated errno value will be returned below. + */ ret = nxsem_wait(sem); @@ -196,34 +204,68 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) wd_cancel(rtcb->waitdog); - if (ret < 0) - { - /* nxsem_wait() failed. Save the errno value */ - - errcode = -ret; - goto errout_with_irqdisabled; - } - /* We can now restore interrupts and delete the watchdog */ - /* Success exits */ - success_with_irqdisabled: - leave_critical_section(flags); - wd_delete(rtcb->waitdog); - rtcb->waitdog = NULL; - leave_cancellation_point(); - return OK; - - /* Error exits */ - errout_with_irqdisabled: leave_critical_section(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; - -errout: - set_errno(errcode); - leave_cancellation_point(); - return ERROR; + return ret; +} + +/**************************************************************************** + * Name: sem_timedwait + * + * Description: + * This function will lock the semaphore referenced by sem as in the + * sem_wait() function. However, if the semaphore cannot be locked without + * waiting for another process or thread to unlock the semaphore by + * performing a sem_post() function, this wait will be terminated when the + * specified timeout expires. + * + * The timeout will expire when the absolute time specified by abstime + * passes, as measured by the clock on which timeouts are based (that is, + * when the value of that clock equals or exceeds abstime), or if the + * absolute time specified by abstime has already been passed at the + * time of the call. + * + * Parameters: + * sem - Semaphore object + * abstime - The absolute time to wait until a timeout is declared. + * + * Return Value: + * Zero (OK) is returned on success. On failure, -1 (ERROR) is returned + * and the errno is set appropriately: + * + * EINVAL The sem argument does not refer to a valid semaphore. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The semaphore could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * EINTR A signal interrupted this function. + * + ****************************************************************************/ + +int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) +{ + int ret; + + /* sem_timedwait() is a cancellation point */ + + (void)enter_cancellation_point(); + + /* Let nxsem_timedout() do the work */ + + ret = nxsem_timedwait(sem, abstime); + if (ret < 0) + { + set_errno(-ret); + ret = ERROR; + } + + leave_cancellation_point(); + return ret; }