linux/kernel/sched/stop_task.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * stop-task scheduling class.
   4 *
   5 * The stop task is the highest priority task in the system, it preempts
   6 * everything and will be preempted by nothing.
   7 *
   8 * See kernel/stop_machine.c
   9 */
  10#include "sched.h"
  11
  12#ifdef CONFIG_SMP
  13static int
  14select_task_rq_stop(struct task_struct *p, int cpu, int flags)
  15{
  16        return task_cpu(p); /* stop tasks as never migrate */
  17}
  18
  19static int
  20balance_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
  21{
  22        return sched_stop_runnable(rq);
  23}
  24#endif /* CONFIG_SMP */
  25
  26static void
  27check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags)
  28{
  29        /* we're never preempted */
  30}
  31
  32static void set_next_task_stop(struct rq *rq, struct task_struct *stop, bool first)
  33{
  34        stop->se.exec_start = rq_clock_task(rq);
  35}
  36
  37static struct task_struct *pick_task_stop(struct rq *rq)
  38{
  39        if (!sched_stop_runnable(rq))
  40                return NULL;
  41
  42        return rq->stop;
  43}
  44
  45static struct task_struct *pick_next_task_stop(struct rq *rq)
  46{
  47        struct task_struct *p = pick_task_stop(rq);
  48
  49        if (p)
  50                set_next_task_stop(rq, p, true);
  51
  52        return p;
  53}
  54
  55static void
  56enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags)
  57{
  58        add_nr_running(rq, 1);
  59}
  60
  61static void
  62dequeue_task_stop(struct rq *rq, struct task_struct *p, int flags)
  63{
  64        sub_nr_running(rq, 1);
  65}
  66
  67static void yield_task_stop(struct rq *rq)
  68{
  69        BUG(); /* the stop task should never yield, its pointless. */
  70}
  71
  72static void put_prev_task_stop(struct rq *rq, struct task_struct *prev)
  73{
  74        struct task_struct *curr = rq->curr;
  75        u64 delta_exec;
  76
  77        delta_exec = rq_clock_task(rq) - curr->se.exec_start;
  78        if (unlikely((s64)delta_exec < 0))
  79                delta_exec = 0;
  80
  81        schedstat_set(curr->se.statistics.exec_max,
  82                        max(curr->se.statistics.exec_max, delta_exec));
  83
  84        curr->se.sum_exec_runtime += delta_exec;
  85        account_group_exec_runtime(curr, delta_exec);
  86
  87        curr->se.exec_start = rq_clock_task(rq);
  88        cgroup_account_cputime(curr, delta_exec);
  89}
  90
  91/*
  92 * scheduler tick hitting a task of our scheduling class.
  93 *
  94 * NOTE: This function can be called remotely by the tick offload that
  95 * goes along full dynticks. Therefore no local assumption can be made
  96 * and everything must be accessed through the @rq and @curr passed in
  97 * parameters.
  98 */
  99static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued)
 100{
 101}
 102
 103static void switched_to_stop(struct rq *rq, struct task_struct *p)
 104{
 105        BUG(); /* its impossible to change to this class */
 106}
 107
 108static void
 109prio_changed_stop(struct rq *rq, struct task_struct *p, int oldprio)
 110{
 111        BUG(); /* how!?, what priority? */
 112}
 113
 114static void update_curr_stop(struct rq *rq)
 115{
 116}
 117
 118/*
 119 * Simple, special scheduling class for the per-CPU stop tasks:
 120 */
 121DEFINE_SCHED_CLASS(stop) = {
 122
 123        .enqueue_task           = enqueue_task_stop,
 124        .dequeue_task           = dequeue_task_stop,
 125        .yield_task             = yield_task_stop,
 126
 127        .check_preempt_curr     = check_preempt_curr_stop,
 128
 129        .pick_next_task         = pick_next_task_stop,
 130        .put_prev_task          = put_prev_task_stop,
 131        .set_next_task          = set_next_task_stop,
 132
 133#ifdef CONFIG_SMP
 134        .balance                = balance_stop,
 135        .pick_task              = pick_task_stop,
 136        .select_task_rq         = select_task_rq_stop,
 137        .set_cpus_allowed       = set_cpus_allowed_common,
 138#endif
 139
 140        .task_tick              = task_tick_stop,
 141
 142        .prio_changed           = prio_changed_stop,
 143        .switched_to            = switched_to_stop,
 144        .update_curr            = update_curr_stop,
 145};
 146