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
commit 774badf5ccb3c99a40f069dc072eeb48b9b580f5 Author: Marco Casaroli <[email protected]> AuthorDate: Tue Nov 3 15:38:59 2026 +0100 sched/mqueue: Wake up all receivers of a System V message queue. msgsnd() woke up only the first receiver that waited for the queue. Each receiver waits for one message type. If the first one wanted another type, it blocked again, and a receiver that wanted the new message stayed blocked while the message was in the queue. Wake up all receivers: each one checks again if a message of its type is in the queue. The senders use the same wake-up code. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- sched/mqueue/msg.h | 10 +++++++ sched/mqueue/msginternal.c | 67 ++++++++++++++++++++++++++++++---------------- sched/mqueue/msgsnd.c | 38 +++----------------------- 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/sched/mqueue/msg.h b/sched/mqueue/msg.h index 6497f1d7ccc..23b3c0ab804 100644 --- a/sched/mqueue/msg.h +++ b/sched/mqueue/msg.h @@ -119,6 +119,16 @@ void nxmsg_free(FAR struct msgq_s *msgq); void nxmsg_wakeup_senders(FAR struct msgq_s *msgq); +/**************************************************************************** + * Name: nxmsg_wakeup_receivers + * + * Description: + * Wake up all tasks that wait in msgrcv() for a message in the queue + * + ****************************************************************************/ + +void nxmsg_wakeup_receivers(FAR struct msgq_s *msgq); + /**************************************************************************** * Name: nxmsg_lookup * diff --git a/sched/mqueue/msginternal.c b/sched/mqueue/msginternal.c index 9a23e566045..d76788c2cb0 100644 --- a/sched/mqueue/msginternal.c +++ b/sched/mqueue/msginternal.c @@ -135,6 +135,42 @@ static void nxmsg_wakeup(FAR struct msgq_s *msgq) } } +/**************************************************************************** + * Name: nxmsg_wakeup_list + * + * Description: + * Wake up all tasks in a wait list of a queue. Each task checks again + * if it can go on. + * + ****************************************************************************/ + +static void nxmsg_wakeup_list(FAR dq_queue_t *list, FAR int16_t *nwait) +{ + FAR struct tcb_s *rtcb = this_task(); + FAR struct tcb_s *btcb; + bool need_switch = false; + + while (*nwait > 0) + { + btcb = (FAR struct tcb_s *)dq_remfirst(list); + DEBUGASSERT(btcb != NULL); + + wd_cancel(&btcb->waitdog); + (*nwait)--; + btcb->waitobj = NULL; + + if (nxsched_add_readytorun(btcb)) + { + need_switch = true; + } + } + + if (need_switch) + { + up_switch_context(this_task(), rtcb); + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -204,31 +240,16 @@ void nxmsg_free(FAR struct msgq_s *msgq) void nxmsg_wakeup_senders(FAR struct msgq_s *msgq) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct tcb_s *btcb; - bool need_switch = false; - - /* Each sender checks again if its message fits */ - - while (msgq->cmn.nwaitnotfull > 0) - { - btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn)); - DEBUGASSERT(btcb != NULL); - - wd_cancel(&btcb->waitdog); - msgq->cmn.nwaitnotfull--; - btcb->waitobj = NULL; + nxmsg_wakeup_list(MQ_WNFLIST(msgq->cmn), &msgq->cmn.nwaitnotfull); +} - if (nxsched_add_readytorun(btcb)) - { - need_switch = true; - } - } +/**************************************************************************** + * Name: nxmsg_wakeup_receivers + ****************************************************************************/ - if (need_switch) - { - up_switch_context(this_task(), rtcb); - } +void nxmsg_wakeup_receivers(FAR struct msgq_s *msgq) +{ + nxmsg_wakeup_list(MQ_WNELIST(msgq->cmn), &msgq->cmn.nwaitnotempty); } /**************************************************************************** diff --git a/sched/mqueue/msgsnd.c b/sched/mqueue/msgsnd.c index 5120fddbeac..e7315950481 100644 --- a/sched/mqueue/msgsnd.c +++ b/sched/mqueue/msgsnd.c @@ -166,7 +166,6 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg) FAR const struct mymsg *buf = msgp; FAR struct msgbuf_s *msg; FAR struct msgq_s *msgq; - FAR struct tcb_s *btcb; irqstate_t flags; int ret = OK; @@ -236,40 +235,11 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg) msgq->lspid = nxsched_getpid(); msgq->stime = time(NULL); - if (msgq->cmn.nwaitnotempty > 0) - { - FAR struct tcb_s *rtcb = this_task(); - - /* Find the highest priority task that is waiting for - * this queue to be non-empty, in the waitfornotempty list of - * the queue. enter_critical_section() should give us sufficient - * protection since interrupts should never cause a change - * in this list - */ - - btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn)); - - /* If one was found, unblock it */ - - DEBUGASSERT(btcb); - - wd_cancel(&btcb->waitdog); - - msgq->cmn.nwaitnotempty--; - - /* Indicate that the wait is over. */ - - btcb->waitobj = NULL; - - /* Add the task to ready-to-run task list and - * perform the context switch if one is needed - */ + /* A receiver waits for one type: the first one may not want this + * message, and another one may. + */ - if (nxsched_add_readytorun(btcb)) - { - up_switch_context(this_task(), rtcb); - } - } + nxmsg_wakeup_receivers(msgq); } errout_with_critical:
