e54b602208
It takes about 10 cycles to obtain the task list according to the task status. In most cases, we know the task status, so we can directly delete the task from the specified task list to reduce time consuming.
115 lines
3.6 KiB
C
115 lines
3.6 KiB
C
/****************************************************************************
|
|
* sched/semaphore/sem_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 <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 "semaphore/semaphore.h"
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: nxsem_wait_irq
|
|
*
|
|
* Description:
|
|
* This function is called when either:
|
|
*
|
|
* 1. A signal is received by a task that is waiting on a semaphore.
|
|
* According to the POSIX spec, "...the calling thread shall not return
|
|
* from the call to [nxsem_wait] until it either locks the semaphore or
|
|
* the call is interrupted by a signal."
|
|
* 2. From logic associated with sem_timedwait(). This function is called
|
|
* when the timeout elapses without receiving the semaphore.
|
|
*
|
|
* Note: this function should used within critical_section
|
|
*
|
|
* Input Parameters:
|
|
* wtcb - A pointer to the TCB of the task that is waiting on a
|
|
* semphaphore, but has received a signal or timeout instead.
|
|
* errcode - EINTR if the semaphore wait was awakened by a signal;
|
|
* ETIMEDOUT if awakened by a timeout
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
* Assumptions:
|
|
*
|
|
****************************************************************************/
|
|
|
|
void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
|
|
{
|
|
FAR struct tcb_s *rtcb = this_task();
|
|
FAR sem_t *sem = wtcb->waitobj;
|
|
|
|
/* It is possible that an interrupt/context switch beat us to the punch
|
|
* and already changed the task's state.
|
|
*/
|
|
|
|
DEBUGASSERT(sem != NULL && sem->semcount < 0);
|
|
|
|
/* Restore the correct priority of all threads that hold references
|
|
* to this semaphore.
|
|
*/
|
|
|
|
nxsem_canceled(wtcb, sem);
|
|
|
|
/* And increment the count on the semaphore. This releases the count
|
|
* that was taken by sem_post(). This count decremented the semaphore
|
|
* count to negative and caused the thread to be blocked in the first
|
|
* place.
|
|
*/
|
|
|
|
sem->semcount++;
|
|
|
|
/* Remove task from waiting list */
|
|
|
|
dq_rem((FAR dq_entry_t *)wtcb, SEM_WAITLIST(sem));
|
|
|
|
/* Indicate that the wait is over. */
|
|
|
|
wtcb->waitobj = NULL;
|
|
|
|
/* Mark the errno 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_unblock_task(wtcb, rtcb);
|
|
}
|
|
}
|