/**************************************************************************** * sched/mqueue/mq_waitirq.c * * 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 #include #include #include #include #include #include #include "mqueue/mqueue.h" #include "sched/sched.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nxmq_wait_irq * * Description: * This function is called when a signal or a timeout is received by a * task that is waiting on a message queue -- either for a queue to * becoming not full (on mq_send and friends) or not empty (on mq_receive * and friends). * Note: this function should used within critical_section * * Input Parameters: * wtcb - A pointer to the TCB of the task that is waiting on a message * queue, but has received a signal instead. * * Returned Value: * None * * Assumptions: * ****************************************************************************/ void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode) { FAR struct tcb_s *rtcb = this_task(); FAR struct mqueue_inode_s *msgq; /* It is possible that an interrupt/context switch beat us to the punch and * already changed the task's state. NOTE: The operations within the if * are safe because interrupts are always disabled with the waitobj, * nwaitnotempty, and nwaitnotfull fields are modified. */ /* Get the message queue associated with the waiter from the TCB */ msgq = wtcb->waitobj; DEBUGASSERT(msgq); /* Decrement the count of waiters and cancel the wait */ if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) { DEBUGASSERT(msgq->cmn.nwaitnotempty > 0); msgq->cmn.nwaitnotempty--; dq_rem((FAR dq_entry_t *)wtcb, MQ_WNELIST(msgq->cmn)); } else { DEBUGASSERT(msgq->cmn.nwaitnotfull > 0); msgq->cmn.nwaitnotfull--; dq_rem((FAR dq_entry_t *)wtcb, MQ_WNFLIST(msgq->cmn)); } /* Indicate that the wait is over. */ wtcb->waitobj = NULL; /* Mark the error value for the thread. */ wtcb->errcode = errcode; /* Add the task to ready-to-run task list and * perform the context switch if one is needed */ if (nxsched_add_readytorun(wtcb)) { up_switch_context(wtcb, rtcb); } }