This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new aa906e76f37 sched/semaphore: Keep uninterruptible waits per task
aa906e76f37 is described below
commit aa906e76f3733c0b11de198e2f588a4a4817e7ad
Author: chao an <[email protected]>
AuthorDate: Wed Oct 28 15:31:45 2026 +0800
sched/semaphore: Keep uninterruptible waits per task
Uninterruptible semaphore helpers marked the semaphore object itself, so one
uninterruptible wait changed EINTR behavior for later normal waiters on the
same semaphore.
Track the uninterruptible state on the waiting task and restore it when the
helper returns so the behavior is limited to the current wait operation.
Signed-off-by: chao an <[email protected]>
---
include/nuttx/sched.h | 1 +
include/nuttx/semaphore.h | 31 ++++++++++++++++++++++++-------
include/semaphore.h | 1 -
libs/libc/semaphore/sem_wait.c | 16 ++++++++++++++--
sched/semaphore/sem_tickwait.c | 8 +++++++-
sched/semaphore/sem_wait.c | 2 +-
sched/signal/sig_dispatch.c | 4 +---
7 files changed, 48 insertions(+), 15 deletions(-)
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index aa6a2914676..59e06a686c9 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -112,6 +112,7 @@
#define TCB_FLAG_FREE_TCB (1 << 15) /* Bit 15:
Free tcb after exit */
#define TCB_FLAG_PREEMPT_SCHED (1 << 16) /* Bit 16:
tcb is PREEMPT_SCHED */
#define TCB_FLAG_SIGMASK_SAVED (1 << 17) /* Bit 17:
sigsavedmask to restore */
+#define TCB_FLAG_UNINTERRUPTIBLE (1 << 18) /* Bit 18:
Blocking wait ignores signals */
/* Values for struct task_group tg_flags */
diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h
index 93966690f34..5756b6564b9 100644
--- a/include/nuttx/semaphore.h
+++ b/include/nuttx/semaphore.h
@@ -73,17 +73,34 @@
#define NXSEM_COUNT(s) ((FAR atomic_t *)&((s)->val.semcount))
#define NXSEM_IS_MUTEX(s) (((s)->flags & SEM_TYPE_MUTEX) != 0)
-/* The uninterruptible waits set SEM_TYPE_UNINTERRUPTIBLE: then a pending
- * signal does not make nxsem_wait_slow() fail at once. Not in user space:
- * there, the flag would also stop a signal from ending sem_wait(), and the
- * retry gets the signal when the system call returns.
+/* The uninterruptible waits set TCB_FLAG_UNINTERRUPTIBLE on the waiting
+ * task: then a pending signal does not make nxsem_wait_slow() fail at once.
+ * Not in user space: there, the flag would also stop a signal from ending
+ * sem_wait(), and the retry gets the signal when the system call returns.
*/
#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
-# define nxsem_set_uninterruptible(s) \
- ((s)->flags |= SEM_TYPE_UNINTERRUPTIBLE)
+# define NXSEM_SET_UNINTERRUPTIBLE(tcb, flags) \
+ do \
+ { \
+ (tcb) = nxsched_self(); \
+ (flags) = (tcb)->flags & TCB_FLAG_UNINTERRUPTIBLE; \
+ (tcb)->flags |= TCB_FLAG_UNINTERRUPTIBLE; \
+ } \
+ while (0)
+
+# define NXSEM_RESTORE_UNINTERRUPTIBLE(tcb, flags) \
+ do \
+ { \
+ if ((flags) == 0) \
+ { \
+ (tcb)->flags &= ~TCB_FLAG_UNINTERRUPTIBLE; \
+ } \
+ } \
+ while (0)
#else
-# define nxsem_set_uninterruptible(s)
+# define NXSEM_SET_UNINTERRUPTIBLE(tcb, flags) do { } while (0)
+# define NXSEM_RESTORE_UNINTERRUPTIBLE(tcb, flags) do { } while (0)
#endif
/* Mutex related helper macros */
diff --git a/include/semaphore.h b/include/semaphore.h
index 24b93a43629..06cdfd07baf 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -46,7 +46,6 @@
#define SEM_PRIO_MASK 3
#define SEM_TYPE_MUTEX 4
-#define SEM_TYPE_UNINTERRUPTIBLE 8 /* The kernel waits without EINTR */
/* Value returned by sem_open() in the event of a failure. */
diff --git a/libs/libc/semaphore/sem_wait.c b/libs/libc/semaphore/sem_wait.c
index 7300587cc04..9c6225ea9d6 100644
--- a/libs/libc/semaphore/sem_wait.c
+++ b/libs/libc/semaphore/sem_wait.c
@@ -220,9 +220,13 @@ int nxsem_wait(FAR sem_t *sem)
int nxsem_wait_uninterruptible(FAR sem_t *sem)
{
+#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
+ FAR struct tcb_s *rtcb;
+ uint32_t flags;
+#endif
int ret;
- nxsem_set_uninterruptible(sem);
+ NXSEM_SET_UNINTERRUPTIBLE(rtcb, flags);
do
{
@@ -232,6 +236,8 @@ int nxsem_wait_uninterruptible(FAR sem_t *sem)
}
while (ret == -EINTR);
+ NXSEM_RESTORE_UNINTERRUPTIBLE(rtcb, flags);
+
return ret;
}
@@ -262,9 +268,13 @@ int nxsem_wait_uninterruptible(FAR sem_t *sem)
int nxsem_clockwait_uninterruptible(FAR sem_t *sem, clockid_t clockid,
FAR const struct timespec *abstime)
{
+#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
+ FAR struct tcb_s *rtcb;
+ uint32_t flags;
+#endif
int ret;
- nxsem_set_uninterruptible(sem);
+ NXSEM_SET_UNINTERRUPTIBLE(rtcb, flags);
do
{
@@ -274,5 +284,7 @@ int nxsem_clockwait_uninterruptible(FAR sem_t *sem,
clockid_t clockid,
}
while (ret == -EINTR);
+ NXSEM_RESTORE_UNINTERRUPTIBLE(rtcb, flags);
+
return ret;
}
diff --git a/sched/semaphore/sem_tickwait.c b/sched/semaphore/sem_tickwait.c
index ff27811864c..96e75bbb6eb 100644
--- a/sched/semaphore/sem_tickwait.c
+++ b/sched/semaphore/sem_tickwait.c
@@ -150,10 +150,14 @@ out:
int nxsem_tickwait_uninterruptible(FAR sem_t *sem, uint32_t delay)
{
+#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
+ FAR struct tcb_s *rtcb;
+ uint32_t flags;
+#endif
clock_t end = clock_delay2abstick(delay);
int ret;
- nxsem_set_uninterruptible(sem);
+ NXSEM_SET_UNINTERRUPTIBLE(rtcb, flags);
for (; ; )
{
@@ -172,5 +176,7 @@ int nxsem_tickwait_uninterruptible(FAR sem_t *sem, uint32_t
delay)
}
}
+ NXSEM_RESTORE_UNINTERRUPTIBLE(rtcb, flags);
+
return ret;
}
diff --git a/sched/semaphore/sem_wait.c b/sched/semaphore/sem_wait.c
index b1bb8c887ca..a25fee25067 100644
--- a/sched/semaphore/sem_wait.c
+++ b/sched/semaphore/sem_wait.c
@@ -103,7 +103,7 @@ int nxsem_wait_slow(FAR sem_t *sem)
* so the check would make every retry fail at once.
*/
- if (!mutex && (sem->flags & SEM_TYPE_UNINTERRUPTIBLE) == 0)
+ if (!mutex && (rtcb->flags & TCB_FLAG_UNINTERRUPTIBLE) == 0)
{
pendingset = nxsig_pendingset(rtcb);
nxsig_nandset(&pendingset, &pendingset, &rtcb->sigprocmask);
diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c
index 01cf27a3b85..67edadd9803 100644
--- a/sched/signal/sig_dispatch.c
+++ b/sched/signal/sig_dispatch.c
@@ -798,15 +798,13 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, FAR
siginfo_t *info,
if (stcb->task_state == TSTATE_WAIT_SEM && !ignored)
{
- FAR sem_t *sem = stcb->waitobj;
-
/* Not for an uninterruptible semaphore in a system call: the
* handler runs only when the call returns, and the wait would
* block again.
*/
if ((stcb->flags & TCB_FLAG_SYSCALL) == 0 ||
- (sem->flags & SEM_TYPE_UNINTERRUPTIBLE) == 0)
+ (stcb->flags & TCB_FLAG_UNINTERRUPTIBLE) == 0)
{
nxsem_wait_irq(stcb, EINTR);
}