Exemple #1
0
static inline lagopus_callout_task_t
s_get(void) {
  lagopus_callout_task_t ret = NULL;

  s_lock_task_q();
  {
    ret = TAILQ_FIRST(&s_chrono_tsk_q);

    if (likely(ret != NULL)) {

      s_lock_task(ret);
      {
        TAILQ_REMOVE(&s_chrono_tsk_q, ret, m_entry);
        (void)s_set_task_state_in_table(ret, TASK_STATE_DEQUEUED);
        ret->m_status = TASK_STATE_DEQUEUED;
        ret->m_is_in_timed_q = false;
      }
      s_unlock_task(ret);

    }
  }
  s_unlock_task_q();

  return ret;
}
Exemple #2
0
lagopus_result_t
lagopus_callout_task_reset_interval(lagopus_callout_task_t *tptr,
                                    lagopus_chrono_t interval) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (likely(tptr != NULL && *tptr != NULL)) {
    if (likely(interval >= CALLOUT_TASK_MIN_INTERVAL)) {
      lagopus_callout_task_t t = *tptr;

      s_lock_task(t);
      {
        if (likely(t->m_status == TASK_STATE_EXECUTING)) {
          t->m_interval_time = interval;
          ret = LAGOPUS_RESULT_OK;
        } else {
          ret = LAGOPUS_RESULT_INVALID_STATE_TRANSITION;
        }
      }
      s_unlock_task(t);

    } else {
      ret = LAGOPUS_RESULT_TOO_SMALL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Exemple #3
0
static inline void
s_do_unsched(lagopus_callout_task_t t) {

  s_lock_task_q();
  {

    s_lock_task(t);
    {
      if (likely(t->m_is_in_timed_q == true)) {

        TAILQ_REMOVE(&s_chrono_tsk_q, t, m_entry);

        if (t->m_status == TASK_STATE_ENQUEUED) {
            (void)s_set_task_state_in_table(t, TASK_STATE_DEQUEUED);
            t->m_status = TASK_STATE_DEQUEUED;
        }

        t->m_is_in_timed_q = false;
      }
    }
    s_unlock_task(t);
      
  }
  s_unlock_task_q();

}
Exemple #4
0
static inline lagopus_result_t
s_get_runnables(lagopus_chrono_t base_abstime,
                lagopus_callout_task_t *tasks, size_t n,
                lagopus_chrono_t *next_wakeup) {
  size_t n_ret = 0LL;
  lagopus_callout_task_t e;
  lagopus_chrono_t the_abstime = base_abstime + CALLOUT_TASK_SCHED_JITTER;

  s_lock_task_q();
  {

    e = TAILQ_FIRST(&s_chrono_tsk_q);

    while (n_ret < n && e != NULL) {
      e = TAILQ_FIRST(&s_chrono_tsk_q);
      if (likely(e != NULL &&
                 e->m_next_abstime <= the_abstime)) {
        TAILQ_REMOVE(&s_chrono_tsk_q, e, m_entry);

        s_lock_task(e);
        {
          (void)s_set_task_state_in_table(e, TASK_STATE_DEQUEUED);
          e->m_status = TASK_STATE_DEQUEUED;
          e->m_is_in_timed_q = false;
        }
        s_unlock_task(e);

        tasks[n_ret++] = e;
      } else {
        break;
      }
    }

    if (likely(next_wakeup != NULL)) {
      e = TAILQ_FIRST(&s_chrono_tsk_q);
      if (e != NULL) {
        *next_wakeup = e->m_next_abstime;
      } else {
        *next_wakeup = -1LL;
      }
    }

  }
  s_unlock_task_q();

  return (lagopus_result_t)n_ret;
}
Exemple #5
0
static inline lagopus_chrono_t
s_peek_current_wakeup_time(void) {
  lagopus_chrono_t ret = -1LL;
  lagopus_callout_task_t t;

  s_lock_task_q();
  {
    t = TAILQ_FIRST(&s_chrono_tsk_q);
    if (t != NULL) {

      s_lock_task(t);
      {
        ret = t->m_next_abstime;
      }
      s_unlock_task(t);

    }
  }
  s_unlock_task_q();

  return ret;
}
Exemple #6
0
static inline lagopus_result_t
s_run_tasks_by_self(const lagopus_callout_task_t * const tasks,
                    lagopus_chrono_t start_time,
                    size_t n) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (likely(tasks != NULL && n > 0)) {
    lagopus_callout_task_t t;
    size_t i;

    for (i = 0; i < n; i++) {
      /*
       * Change the state of tasks to TASK_STATE_DEQUEUED and set
       * the last execution (start) time as now.
       */
      t = tasks[i];

      s_lock_task(t);
      {
        if (t->m_status == TASK_STATE_ENQUEUED ||
            t->m_status == TASK_STATE_CREATED) {
          (void)s_set_task_state_in_table(t, TASK_STATE_DEQUEUED);
          t->m_status = TASK_STATE_DEQUEUED;
        }
        t->m_last_abstime = start_time;
      }
      s_unlock_task(t);

      (void)s_exec_task(t);
    }

    ret = (lagopus_result_t)n;
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Exemple #7
0
static inline lagopus_chrono_t
s_do_sched(lagopus_callout_task_t t) {
  lagopus_result_t ret = -1LL;
  lagopus_result_t r;
  lagopus_callout_task_t e;

  s_lock_task_q();
  {

    s_lock_task(t);
    {
      if (likely(t->m_is_in_timed_q == false)) {

        /*
         * Firstly (re-)compute the next exeution time of this
         * task.
         */
        if (t->m_is_first == false && t->m_do_repeat == true) {
          t->m_next_abstime = t->m_last_abstime + t->m_interval_time;
        } else {
          WHAT_TIME_IS_IT_NOW_IN_NSEC(t->m_last_abstime);
          t->m_next_abstime = t->m_last_abstime + t->m_initial_delay_time;
        }

        /*
         * Then insert the task into the Q.
         */
        e = TAILQ_FIRST(&s_chrono_tsk_q);
        if (e != NULL) {
          if (e->m_next_abstime > t->m_next_abstime) {
            TAILQ_INSERT_HEAD(&s_chrono_tsk_q, t, m_entry);
          } else {
            for (;
                 e != NULL && e->m_next_abstime <= t->m_next_abstime;
                 e = TAILQ_NEXT(e, m_entry)) {
              ;
            }
            if (e != NULL) {
              TAILQ_INSERT_BEFORE(e, t, m_entry);
            } else {
              TAILQ_INSERT_TAIL(&s_chrono_tsk_q, t, m_entry);
            }
          }
        } else {
          TAILQ_INSERT_TAIL(&s_chrono_tsk_q, t, m_entry);
        }

        (void)s_set_task_state_in_table(t, TASK_STATE_ENQUEUED);
        t->m_status = TASK_STATE_ENQUEUED;
        t->m_is_in_timed_q = true;

        ret = t->m_next_abstime;

        /*
         * Fianlly wake the master scheduler.
         */
        lagopus_msg_debug(4, "wake the master scheduler up.\n");

        /*
         * TODO
         *
         *	Re-optimize forcible wake up by timed task submission
         *	timing and times. See also
         *	callout.c:s_start_callout_main_loop()
         */

        r = lagopus_bbq_wakeup(&s_urgent_tsk_q, 0LL);
        if (unlikely(r != LAGOPUS_RESULT_OK)) {
          lagopus_perror(r);
          lagopus_msg_error("can't wake the callout task master "
                            "scheduler up.\n");
        }
      }
    }
    s_unlock_task(t);

  }
  s_unlock_task_q();

  return ret;
}