mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 14:53:47 +08:00
Revert "sched: Remove a redundant critical section"
There is a potential problem that can lead to deadlock at condition wait, if the timeout of watchdog is a very small value (1 tick ?), the timer interrupt will come before the nxsem_wait() Revert "sched: pthread: Remove a redundant critical section in pthread_condclockwsait.c" Revert "sched: semaphore: Remove a redundant critical section in nxsem_clockwait()" Revert "sched: semaphore: Remove a redundant critical section in nxsem_tickwait()" This reverts commit7758f3dcb1. This reverts commit2976bb212e. This reverts commit65dec5d10a. Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
committed by
Masayuki Ishikawa
parent
0b7b8d274f
commit
102a6357ca
@@ -92,6 +92,7 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
FAR const struct timespec *abstime)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
irqstate_t flags;
|
||||
sclock_t ticks;
|
||||
int status;
|
||||
int ret = ERROR;
|
||||
@@ -109,11 +110,16 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* NOTE: We do not need a critical section here, because
|
||||
* nxsem_wait() and nxsem_timeout() use a critical section
|
||||
* in the functions.
|
||||
/* We will disable interrupts until we have completed the semaphore
|
||||
* wait. We need to do this (as opposed to just disabling pre-emption)
|
||||
* because there could be interrupt handlers that are asynchronously
|
||||
* posting semaphores and to prevent race conditions with watchdog
|
||||
* timeout. This is not too bad because interrupts will be re-
|
||||
* enabled while we are blocked waiting for the semaphore.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Try to take the semaphore without waiting. */
|
||||
|
||||
ret = nxsem_trywait(sem);
|
||||
@@ -121,7 +127,7 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
{
|
||||
/* We got it! */
|
||||
|
||||
goto out;
|
||||
goto success_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* We will have to wait for the semaphore. Make sure that we were provided
|
||||
@@ -131,7 +137,7 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
goto errout_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* Convert the timespec to clock ticks. We must have interrupts
|
||||
@@ -148,7 +154,7 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
if (status == OK && ticks <= 0)
|
||||
{
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
goto errout_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* Handle any time-related errors */
|
||||
@@ -156,7 +162,7 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
if (status != OK)
|
||||
{
|
||||
ret = -status;
|
||||
goto out;
|
||||
goto errout_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* Start the watchdog */
|
||||
@@ -173,7 +179,11 @@ int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||
|
||||
wd_cancel(&rtcb->waitdog);
|
||||
|
||||
out:
|
||||
/* We can now restore interrupts and delete the watchdog */
|
||||
|
||||
success_with_irqdisabled:
|
||||
errout_with_irqdisabled:
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,16 +71,22 @@
|
||||
int nxsem_tickwait(FAR sem_t *sem, clock_t start, uint32_t delay)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
irqstate_t flags;
|
||||
clock_t elapsed;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(sem != NULL && up_interrupt_context() == false);
|
||||
|
||||
/* NOTE: We do not need a critical section here, because
|
||||
* nxsem_wait() and nxsem_timeout() use a critical section
|
||||
* in the functions.
|
||||
/* We will disable interrupts until we have completed the semaphore
|
||||
* wait. We need to do this (as opposed to just disabling pre-emption)
|
||||
* because there could be interrupt handlers that are asynchronously
|
||||
* posting semaphores and to prevent race conditions with watchdog
|
||||
* timeout. This is not too bad because interrupts will be re-
|
||||
* enabled while we are blocked waiting for the semaphore.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Try to take the semaphore without waiting. */
|
||||
|
||||
ret = nxsem_trywait(sem);
|
||||
@@ -88,7 +94,7 @@ int nxsem_tickwait(FAR sem_t *sem, clock_t start, uint32_t delay)
|
||||
{
|
||||
/* We got it! */
|
||||
|
||||
goto out;
|
||||
goto success_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* We will have to wait for the semaphore. Make sure that we were provided
|
||||
@@ -99,7 +105,7 @@ int nxsem_tickwait(FAR sem_t *sem, clock_t start, uint32_t delay)
|
||||
{
|
||||
/* Return the errno from nxsem_trywait() */
|
||||
|
||||
goto out;
|
||||
goto errout_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* Adjust the delay for any time since the delay was calculated */
|
||||
@@ -108,7 +114,7 @@ int nxsem_tickwait(FAR sem_t *sem, clock_t start, uint32_t delay)
|
||||
if (/* elapsed >= (UINT32_MAX / 2) || */ elapsed >= delay)
|
||||
{
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
goto errout_with_irqdisabled;
|
||||
}
|
||||
|
||||
delay -= elapsed;
|
||||
@@ -125,8 +131,21 @@ int nxsem_tickwait(FAR sem_t *sem, clock_t start, uint32_t delay)
|
||||
|
||||
wd_cancel(&rtcb->waitdog);
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_irqdisabled;
|
||||
}
|
||||
|
||||
/* We can now restore interrupts */
|
||||
|
||||
/* Success exits */
|
||||
|
||||
success_with_irqdisabled:
|
||||
|
||||
/* Error exits */
|
||||
|
||||
errout_with_irqdisabled:
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user