Ejemplo n.º 1
0
void up_block_task(FAR _TCB *tcb, tstate_t task_state)
{
  /* Verify that the context switch can be performed */

  if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) ||
      (tcb->task_state > LAST_READY_TO_RUN_STATE))
    {
      PANIC(OSERR_BADBLOCKSTATE);
    }
  else
    {
      FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
      bool switch_needed;

      /* dbg("Blocking TCB=%p\n", tcb); */

      /* Remove the tcb task from the ready-to-run list.  If we
       * are blocking the task at the head of the task list (the
       * most likely case), then a context switch to the next
       * ready-to-run task is needed. In this case, it should
       * also be true that rtcb == tcb.
       */

      switch_needed = sched_removereadytorun(tcb);

      /* Add the task to the specified blocked task list */

      sched_addblocked(tcb, (tstate_t)task_state);

      /* If there are any pending tasks, then add them to the g_readytorun
       * task list now
       */

      if (g_pendingtasks.head)
        {
          switch_needed |= sched_mergepending();
        }

      /* Now, perform the context switch if one is needed */

      if (switch_needed)
        {
          /* Are we in an interrupt handler? */

          if (IN_INTERRUPT)
            {
              /* Yes, then we have to do things differently.
               * Just copy the current registers into the OLD rtcb.
               */

               SAVE_IRQCONTEXT(rtcb);

              /* Restore the exception context of the rtcb at the (new) head 
               * of the g_readytorun task list.
               */

              rtcb = (FAR _TCB*)g_readytorun.head;
              /* dbg("New Active Task TCB=%p\n", rtcb); */

              /* Then setup so that the context will be performed on exit
               * from the interrupt.
               */

              SET_IRQCONTEXT(rtcb);
            }

          /* Copy the user C context into the TCB at the (old) head of the
           * g_readytorun Task list. if SAVE_USERCONTEXT returns a non-zero
           * value, then this is really the previously running task restarting!
           */

          else if (!SAVE_USERCONTEXT(rtcb))
            {
              /* Restore the exception context of the rtcb at the (new) head 
               * of the g_readytorun task list.
               */

              rtcb = (FAR _TCB*)g_readytorun.head;
              /* dbg("New Active Task TCB=%p\n", rtcb); */

              /* Then switch contexts */

              RESTORE_USERCONTEXT(rtcb);
            }
        }
    }
}
Ejemplo n.º 2
0
void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
  bool switch_needed;

  /* Verify that the context switch can be performed */

  ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) &&
         (tcb->task_state <= LAST_READY_TO_RUN_STATE));

  /* dbg("Blocking TCB=%p\n", tcb); */

  /* Remove the tcb task from the ready-to-run list.  If we
   * are blocking the task at the head of the task list (the
   * most likely case), then a context switch to the next
   * ready-to-run task is needed. In this case, it should
   * also be true that rtcb == tcb.
   */

  switch_needed = sched_removereadytorun(tcb);

  /* Add the task to the specified blocked task list */

  sched_addblocked(tcb, (tstate_t)task_state);

  /* If there are any pending tasks, then add them to the g_readytorun
   * task list now
   */

  if (g_pendingtasks.head)
    {
      switch_needed |= sched_mergepending();
    }

  /* Now, perform the context switch if one is needed */

  if (switch_needed)
    {
      /* Are we in an interrupt handler? */

      if (IN_INTERRUPT())
        {
          /* Yes, then we have to do things differently.
           * Just copy the current registers into the OLD rtcb.
           */

          SAVE_IRQCONTEXT(rtcb);

          /* Restore the exception context of the rtcb at the (new) head
           * of the g_readytorun task list.
           */

          rtcb = (FAR struct tcb_s*)g_readytorun.head;
          /* dbg("New Active Task TCB=%p\n", rtcb); */

          /* Then setup so that the context will be performed on exit
           * from the interrupt.  Any necessary address environment
           * changes will be made when the interrupt returns.
           */

          SET_IRQCONTEXT(rtcb);
        }

      /* Copy the user C context into the TCB at the (old) head of the
       * g_readytorun Task list. if SAVE_USERCONTEXT returns a non-zero
       * value, then this is really the previously running task restarting!
       */

      else if (!SAVE_USERCONTEXT(rtcb))
        {
          /* Restore the exception context of the rtcb at the (new) head
           * of the g_readytorun task list.
           */

          rtcb = (FAR struct tcb_s*)g_readytorun.head;

#ifdef CONFIG_ARCH_ADDRENV
         /* Make sure that the address environment for the previously
          * running task is closed down gracefully (data caches dump,
          * MMU flushed) and set up the address environment for the new
          * thread at the head of the ready-to-run list.
          */

         (void)group_addrenv(rtcb);
#endif
          /* Then switch contexts */

          RESTORE_USERCONTEXT(rtcb);
        }
    }
}
Ejemplo n.º 3
0
void up_reprioritize_rtr(FAR struct tcb_s *tcb, uint8_t priority)
{
    /* Verify that the caller is sane */

    if (tcb->task_state < FIRST_READY_TO_RUN_STATE ||
            tcb->task_state > LAST_READY_TO_RUN_STATE
#if SCHED_PRIORITY_MIN > 0
            || priority < SCHED_PRIORITY_MIN
#endif
#if SCHED_PRIORITY_MAX < UINT8_MAX
            || priority > SCHED_PRIORITY_MAX
#endif
       )
    {
        PANIC();
    }
    else
    {
        FAR struct tcb_s *rtcb = this_task();
        bool switch_needed;

        slldbg("TCB=%p PRI=%d\n", tcb, priority);

        /* Remove the tcb task from the ready-to-run list.
         * sched_removereadytorun will return true if we just
         * remove the head of the ready to run list.
         */

        switch_needed = sched_removereadytorun(tcb);

        /* Setup up the new task priority */

        tcb->sched_priority = (uint8_t)priority;

        /* Return the task to the specified blocked task list.
         * sched_addreadytorun will return true if the task was
         * added to the new list.  We will need to perform a context
         * switch only if the EXCLUSIVE or of the two calls is non-zero
         * (i.e., one and only one the calls changes the head of the
         * ready-to-run list).
         */

        switch_needed ^= sched_addreadytorun(tcb);

        /* Now, perform the context switch if one is needed */

        if (switch_needed)
        {
            /* If we are going to do a context switch, then now is the right
             * time to add any pending tasks back into the ready-to-run list.
             * task list now
             */

            if (g_pendingtasks.head)
            {
                sched_mergepending();
            }

            /* Update scheduler parameters */

            sched_suspend_scheduler(rtcb);

            /* Are we in an interrupt handler? */

            if (IN_INTERRUPT)
            {
                /* Yes, then we have to do things differently.
                 * Just copy the current context into the OLD rtcb.
                 */

                SAVE_IRQCONTEXT(rtcb);

                /* 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 setup so that the context will be performed on exit
                 * from the interrupt.
                 */

                SET_IRQCONTEXT(rtcb);
            }

            /* Copy the exception context into the TCB at the (old) head of the
             * ready-to-run Task list. if SAVE_USERCONTEXT returns a non-zero
             * value, then this is really the previously running task restarting!
             */

            else if (!SAVE_USERCONTEXT(rtcb))
            {
                /* 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 */

                RESTORE_USERCONTEXT(rtcb);
            }
        }
    }
}
Ejemplo n.º 4
0
void up_release_pending(void)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;

  slldbg("From TCB=%p\n", rtcb);

  /* Merge the g_pendingtasks list into the g_readytorun task list */

  /* sched_lock(); */
  if (sched_mergepending())
    {
      /* The currently active task has changed!  We will need to switch
       * contexts.
       *
       * Update scheduler parameters.
       */

      sched_suspend_scheduler(rtcb);

      /* Are we operating in interrupt context? */

      if (IN_INTERRUPT)
        {
          /* Yes, then we have to do things differently.
           * Just copy the current context into the OLD rtcb.
           */

           SAVE_IRQCONTEXT(rtcb);

          /* Restore the exception context of the rtcb at the (new) head
           * of the g_readytorun task list.
           */

          rtcb = (FAR struct tcb_s*)g_readytorun.head;

          /* Update scheduler parameters */

          sched_resume_scheduler(rtcb);

          /* Then setup so that the context will be performed on exit
           * from the interrupt.
           */

          SET_IRQCONTEXT(rtcb);
        }

      /* Copy the exception context into the TCB of the task that
       * was currently active. if SAVE_USERCONTEXT returns a non-zero
       * value, then this is really the previously running task
       * restarting!
       */

      else if (!SAVE_USERCONTEXT(rtcb))
        {
          /* Restore the exception context of the rtcb at the (new) head
           * of the g_readytorun task list.
           */

          rtcb = (FAR struct tcb_s*)g_readytorun.head;

          /* Update scheduler parameters */

          sched_resume_scheduler(rtcb);

          /* Then switch contexts */

          RESTORE_USERCONTEXT(rtcb);
        }
    }
}
Ejemplo n.º 5
0
void up_release_pending(void)
{
  FAR struct tcb_s *rtcb = this_task();

  slldbg("From TCB=%p\n", rtcb);

  /* Merge the g_pendingtasks list into the ready-to-run task list */

  /* sched_lock(); */
  if (sched_mergepending())
    {
      /* The currently active task has changed!  We will need to switch
       * contexts.
       *
       * Update scheduler parameters.
       */

      sched_suspend_scheduler(rtcb);

      /* Are we operating in interrupt context? */

      if (IN_INTERRUPT())
        {
          /* Yes, then we have to do things differently.
           * Just copy the current context into the OLD rtcb.
           */

           SAVE_IRQCONTEXT(rtcb);

          /* 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 setup so that the context will be performed on exit
           * from the interrupt.  Any necessary address environment
           * changes will be made when the interrupt returns.
           */

          SET_IRQCONTEXT(rtcb);
        }

      /* Copy the exception context into the TCB of the task that
       * was currently active. if SAVE_USERCONTEXT returns a non-zero
       * value, then this is really the previously running task
       * restarting!
       */

      else if (!SAVE_USERCONTEXT(rtcb))
        {
          /* Restore the exception context of the rtcb at the (new) head
           * of the ready-to-run task list.
           */

          rtcb = this_task();

#ifdef CONFIG_ARCH_ADDRENV
          /* Make sure that the address environment for the previously
           * running task is closed down gracefully (data caches dump,
           * MMU flushed) and set up the address environment for the new
           * thread at the head of the ready-to-run list.
           */

          (void)group_addrenv(rtcb);
#endif
          /* Update scheduler parameters */

          sched_resume_scheduler(rtcb);

          /* Then switch contexts */

          RESTORE_USERCONTEXT(rtcb);
        }
    }
}
Ejemplo n.º 6
0
void up_unblock_task(FAR _TCB *tcb)
{
  /* Verify that the context switch can be performed */

  if ((tcb->task_state < FIRST_BLOCKED_STATE) ||
      (tcb->task_state > LAST_BLOCKED_STATE))
    {
      PANIC(OSERR_BADUNBLOCKSTATE);
    }
  else
    {
      FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;

      /* dbg("Unblocking TCB=%p\n", tcb); */

      /* Remove the task from the blocked task list */

      sched_removeblocked(tcb);

      /* Reset its timeslice.  This is only meaningful for round
       * robin tasks but it doesn't here to do it for everything
       */

#if CONFIG_RR_INTERVAL > 0
      tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK;
#endif

      /* Add the task in the correct location in the prioritized
       * g_readytorun task list
       */

      if (sched_addreadytorun(tcb))
        {
          /* The currently active task has changed! We need to do
           * a context switch to the new task.
           *
           * Are we in an interrupt handler? 
           */

          if (IN_INTERRUPT)
            {
              /* Yes, then we have to do things differently.
               * Just copy the current context into the OLD rtcb.
               */

               SAVE_IRQCONTEXT(rtcb);

              /* Restore the exception context of the rtcb at the (new) head 
               * of the g_readytorun task list.
               */

              rtcb = (FAR _TCB*)g_readytorun.head;
              /* dbg("New Active Task TCB=%p\n", rtcb); */

              /* Then setup so that the context will be performed on exit
               * from the interrupt.
               */

              SET_IRQCONTEXT(rtcb);
            }

          /* We are not in an interrupt handler.  Copy the user C context
           * into the TCB of the task that was previously active.  if 
           * SAVE_USERCONTEXT returns a non-zero value, then this is really the
           * previously running task restarting!
           */

          else if (!SAVE_USERCONTEXT(rtcb))
            {
              /* Restore the exception context of the new task that is ready to
               * run (probably tcb).  This is the new rtcb at the head of the
               * g_readytorun task list.
               */

              rtcb = (FAR _TCB*)g_readytorun.head;
              /* dbg("New Active Task TCB=%p\n", rtcb); */

              /* Then switch contexts */

              RESTORE_USERCONTEXT(rtcb);
            }
        }
    }
}