Example #1
0
static inline void sched_process_timeslice(void)
{
  FAR struct tcb_s *rtcb  = (FAR struct tcb_s*)g_readytorun.head;

  /* Check if the currently executing task uses round robin
   * scheduling.
   */

  if ((rtcb->flags & TCB_FLAG_ROUND_ROBIN) != 0)
    {
      /* Yes, check if decrementing the timeslice counter
       * would cause the timeslice to expire
       */

      if (rtcb->timeslice <= 1)
        {
          /* Yes, Now check if the task has pre-emption disabled.
           * If so, then we will freeze the timeslice count at
           * the value until the next tick after pre-emption
           * has been enabled.
           */

          if (!rtcb->lockcount)
            {
              /* Reset the timeslice in any case. */

              rtcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK;

              /* We know we are at the head of the ready to run
               * prioritized list.  We must be the highest priority
               * task eligible for execution.  Check the next task
               * in the ready to run list.  If it is the same
               * priority, then we need to relinquish the CPU and
               * give that task a shot.
               */

              if (rtcb->flink &&
                  rtcb->flink->sched_priority >= rtcb->sched_priority)
                {
                  /* Just resetting the task priority to its current
                   * value.  This this will cause the task to be
                   * rescheduled behind any other tasks at the same
                   * priority.
                   */

                  up_reprioritize_rtr(rtcb, rtcb->sched_priority);
                }
            }
        }
      else
        {
          /* Decrement the timeslice counter */

          rtcb->timeslice--;
        }
    }
}
Example #2
0
int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
  tstate_t task_state;
  irqstate_t saved_state;

  /* Verify that the requested priority is in the valid range */

  if (sched_priority < SCHED_PRIORITY_MIN ||
      sched_priority > SCHED_PRIORITY_MAX)
    {
      set_errno(EINVAL);
      return ERROR;
    }

  /* We need to assure that there there is no interrupt activity while
   * performing the following.
   */

  saved_state = irqsave();

  /* There are four cases that must be considered: */

  task_state = tcb->task_state;
  switch (task_state)
    {
      /* CASE 1. The task is running or ready-to-run and a context switch
       * may be caused by the re-prioritization
       */

      case TSTATE_TASK_RUNNING:

        /* A context switch will occur if the new priority of the running
         * task becomes less than OR EQUAL TO the next highest priority
         * ready to run task.
         */

        if (sched_priority <= tcb->flink->sched_priority)
          {
            /* A context switch will occur. */

            up_reprioritize_rtr(tcb, (uint8_t)sched_priority);
          }

        /* Otherwise, we can just change priority since it has no effect */

        else
          {
            /* Change the task priority */

            tcb->sched_priority = (uint8_t)sched_priority;
          }
        break;

      /* CASE 2. The task is running or ready-to-run and a context switch
       * may be caused by the re-prioritization
       */

      case TSTATE_TASK_READYTORUN:

        /* A context switch will occur if the new priority of the ready-to
         * run task is (strictly) greater than the current running task
         */

        if (sched_priority > rtcb->sched_priority)
          {
            /* A context switch will occur. */

            up_reprioritize_rtr(tcb, (uint8_t)sched_priority);
          }

        /* Otherwise, we can just change priority and re-schedule (since it
         * have no other effect).
         */

        else
          {
            /* Remove the TCB from the ready-to-run task list */

            ASSERT(!sched_removereadytorun(tcb));

            /* Change the task priority */

            tcb->sched_priority = (uint8_t)sched_priority;

            /* Put it back into the ready-to-run task list */

            ASSERT(!sched_addreadytorun(tcb));
          }
        break;

      /* CASE 3. The task is not in the ready to run list.  Changing its
       * Priority cannot effect the currently executing task.
       */

      default:

        /* CASE 3a. The task resides in a prioritized list. */

        if (g_tasklisttable[task_state].prioritized)
          {
            /* Remove the TCB from the prioritized task list */

            dq_rem((FAR dq_entry_t*)tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list);

            /* Change the task priority */

            tcb->sched_priority = (uint8_t)sched_priority;

            /* Put it back into the prioritized list at the correct
             * position
             */

            sched_addprioritized(tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list);
          }

        /* CASE 3b. The task resides in a non-prioritized list. */

        else
          {
            /* Just change the task's priority */

            tcb->sched_priority = (uint8_t)sched_priority;
          }
        break;
    }

  irqrestore(saved_state);
  return OK;
}
uint32_t sched_roundrobin_process(FAR struct tcb_s *tcb, uint32_t ticks,
                                  bool noswitches)
{
  uint32_t ret;
  int decr;

  /* How much can we decrement the timeslice delay?  If 'ticks' is greater
   * than the timeslice value, then we ignore any excess amount.
   *
   * 'ticks' should never be greater than the remaining timeslice.  We try
   * to handle that gracefully but it would be an error in the scheduling
   * if there ever were the case.
   */

  DEBUGASSERT(tcb != NULL && ticks <= tcb->timeslice);
  decr = MIN(tcb->timeslice, ticks);

  /* Decrement the timeslice counter */

  tcb->timeslice -= decr;

  /* Did decrementing the timeslice counter cause the timeslice to expire?
   *
   * If the task has pre-emption disabled. Then we will let the timeslice
   * count go negative as a indication of this situation.
   */

  ret = tcb->timeslice;
  if (tcb->timeslice <= 0 && tcb->lockcount == 0)
    {
      /* We will also suppress context switches if we were called via one
       * of the unusual cases handled by sched_timer_reasses().  In that
       * case, we will return a value of one so that the timer will expire
       * as soon as possible and we can perform this action in the normal
       * timer expiration context.
       *
       * This is kind of kludge, but I am not to concerned because I hope
       * that the situation is impossible or at least could only occur on
       * rare corner-cases.
       */

      if (noswitches)
        {
          ret = 1;
        }
      else
        {
          /* Reset the timeslice. */

          tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
          ret = tcb->timeslice;

          /* We know we are at the head of the ready to run prioritized
           * list.  We must be the highest priority task eligible for
           * execution.  Check the next task in the ready to run list.  If
           * it is the same priority, then we need to relinquish the CPU and
           * give that task a shot.
           */

          if (tcb->flink &&
              tcb->flink->sched_priority >= tcb->sched_priority)
            {
              /* Just resetting the task priority to its current value.
               * This this will cause the task to be rescheduled behind any
               * other tasks at the same priority.
               */

              up_reprioritize_rtr(tcb, tcb->sched_priority);
            }
        }
    }

  return ret;
}