mirror of
https://github.com/apache/nuttx.git
synced 2025-12-10 20:24:51 +08:00
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:
committed by
Alan C. Assis
parent
735e489070
commit
39f54c1524
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
92
sched/event/event_waitirq.c
Normal file
92
sched/event/event_waitirq.c
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user