/**************************************************************************** * arch/arm/src/armv8-m/arm_unblocktask.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 "sched/sched.h" #include "clock/clock.h" #include "arm_internal.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: up_unblock_task * * Description: * A task is currently in an inactive task list * but has been prepped to execute. Move the TCB to the * ready-to-run list, restore its context, and start execution. * * Input Parameters: * tcb: Refers to the tcb to be unblocked. This tcb is * in one of the waiting tasks lists. It must be moved to * the ready-to-run list and, if it is the highest priority * ready to run task, executed. * ****************************************************************************/ void up_unblock_task(struct tcb_s *tcb) { struct tcb_s *rtcb = this_task(); /* Verify that the context switch can be performed */ DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && (tcb->task_state <= LAST_BLOCKED_STATE)); /* Remove the task from the blocked task list */ sched_removeblocked(tcb); /* Add the task in the correct location in the prioritized * ready-to-run task list */ if (sched_addreadytorun(tcb)) { /* The currently active task has changed! We need to do * a context switch to the new task. */ /* Update scheduler parameters */ sched_suspend_scheduler(rtcb); /* Are we in an interrupt handler? */ if (CURRENT_REGS) { /* Yes, then we have to do things differently. * Just copy the CURRENT_REGS into the OLD rtcb. */ arm_savestate(rtcb->xcp.regs); /* Restore the exception context of the rtcb at the (new) head * of the ready-to-run task list. */ rtcb = this_task(); /* Update scheduler parameters */ sched_resume_scheduler(rtcb); /* Then switch contexts */ arm_restorestate(rtcb->xcp.regs); } /* No, then we will need to perform the user context switch */ else { struct tcb_s *nexttcb = this_task(); /* Update scheduler parameters */ sched_resume_scheduler(nexttcb); /* Switch context to the context of the task at the head of the * ready to run list. */ arm_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); /* arm_switchcontext forces a context switch to the task at the * head of the ready-to-run list. It does not 'return' in the * normal sense. When it does return, it is because the blocked * task is again ready to run and has execution priority. */ } } }