sched/event: Add nxevent_wait_irq() to handle the task cancel

If the thread is blocked waiting on a event, then the
    thread must be unblocked from the evnet to handle
    the task cancellation.

Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
This commit is contained in:
wangchengdong
2025-10-29 10:38:17 +08:00
committed by Alan C. Assis
parent 735e489070
commit 39f54c1524
7 changed files with 118 additions and 6 deletions

View File

@@ -32,7 +32,8 @@ if(CONFIG_SCHED_EVENTS)
event_destroy.c
event_wait.c
event_clear.c
event_getmask.c)
event_getmask.c
event_waitirq.c)
endif()
target_sources(sched PRIVATE ${CSRCS})

View File

@@ -24,6 +24,7 @@
ifeq ($(CONFIG_SCHED_EVENTS),y)
CSRCS += event_init.c event_post.c event_reset.c event_destroy.c event_wait.c event_clear.c event_getmask.c
CSRCS += event_waitirq.c
endif
# Include event build support

View File

@@ -31,12 +31,13 @@
#include <nuttx/irq.h>
#include <nuttx/list.h>
#include <nuttx/semaphore.h>
#include <nuttx/event.h>
/****************************************************************************
* Public Type Definitions
* Public Function Definitions
****************************************************************************/
void nxevent_wait_irq(FAR struct tcb_s *wtcb, int errcode);
#endif /* __SCHED_EVENT_EVENT_H */

View File

@@ -118,6 +118,8 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events,
wtcb = wait->wtcb;
wtcb->waitobj = NULL;
/* Remove the task from waiting list */
dq_rem((FAR dq_entry_t *)wtcb, list_waitingforsignal());

View File

@@ -60,8 +60,8 @@ static void nxevent_timeout(wdparm_t arg)
/* Get waiting tcb from parameter */
wait = (FAR nxevent_wait_t *)(uintptr_t)arg;
wtcb = wait->wtcb;
wtcb = (FAR struct tcb_s *)(uintptr_t)arg;
wait = wtcb->waitobj;
/* We must be in a critical section in order to call up_switch_context()
* below.
@@ -82,6 +82,8 @@ static void nxevent_timeout(wdparm_t arg)
list_delete(&(wait->node));
}
wtcb->waitobj = NULL;
/* Mark the errno value for the thread. */
wtcb->errcode = ETIMEDOUT;
@@ -199,13 +201,14 @@ nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event,
/* Initialize event wait */
wtcb = this_task();
wtcb->waitobj = (FAR void *)wait;
wait->expect = events;
wait->eflags = eflags;
wait->wtcb = wtcb;
list_add_tail(&event->list, &(wait->node));
wd_start(&wtcb->waitdog, delay, nxevent_timeout, (uintptr_t)&wait);
wd_start(&wtcb->waitdog, delay, nxevent_timeout, (uintptr_t)wtcb);
/* Remove the tcb task from the ready-to-run list. */

View File

@@ -0,0 +1,92 @@
/****************************************************************************
* sched/event/event_waitirq.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sched.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include "sched/sched.h"
#include "event/event.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxevent_wait_irq
*
* Description:
* An error event has occurred and the event wait must be terminated with
* an error.
*
****************************************************************************/
void nxevent_wait_irq(FAR struct tcb_s *wtcb, int errcode)
{
/* It is possible that an interrupt/context switch beat us to the punch
* and already changed the task's state.
*/
DEBUGASSERT(wtcb != NULL);
FAR struct tcb_s *rtcb = this_task();
FAR nxevent_wait_t *wait = wtcb->waitobj;
DEBUGASSERT(wait != NULL);
/* Remove the wait structure from the event's waiting list */
if (list_in_list(&(wait->node)))
{
list_delete(&(wait->node));
}
/* Remove the task from the event waiting list */
dq_rem((FAR dq_entry_t *)wtcb, list_waitingforsignal());
/* Indicate that the wait is over */
wtcb->waitobj = NULL;
/* Store the error code for the thread */
wtcb->errcode = errcode;
/* Add the task to the ready-to-run list and perform a context
* switch if one is needed.
*/
if (nxsched_add_readytorun(wtcb))
{
up_switch_context(this_task(), rtcb);
}
}

View File

@@ -67,6 +67,7 @@
#include "signal/signal.h"
#include "mqueue/mqueue.h"
#include "task/task.h"
#include "event/event.h"
/****************************************************************************
* Public Functions
@@ -165,6 +166,17 @@ bool nxnotify_cancellation(FAR struct tcb_s *tcb)
nxsig_wait_irq(tcb, SIG_CANCEL_TIMEOUT, SI_USER, ECANCELED);
}
#ifdef CONFIG_SCHED_EVENTS
/* If the thread is blocked waiting on a event, then the
* thread must be unblocked to handle the cancellation.
*/
else if (tcb->task_state == TSTATE_WAIT_EVENT)
{
nxevent_wait_irq(tcb, ECANCELED);
}
#endif
#if !defined(CONFIG_DISABLE_MQUEUE) || !defined(CONFIG_DISABLE_MQUEUE_SYSV)
/* If the thread is blocked waiting on a message queue, then
* the thread must be unblocked to handle the cancellation.