// SPDX-License-Identifier: GPL-2.0 /* * Deadline Scheduling Class (SCHED_DEADLINE) * * Earliest Deadline First (EDF) + Constant Bandwidth Server (CBS). * * Tasks that periodically executes their instances for less than their * runtime won't miss any of their deadlines. * Tasks that are not periodic or sporadic or that tries to execute more * than their reserved bandwidth will be slowed down (and may potentially * miss some of their deadlines), and won't affect any other task. * * Copyright (C) 2012 Dario Faggioli <[email protected]>, * Juri Lelli <[email protected]>, * Michael Trimarchi <[email protected]>, * Fabio Checconi <[email protected]> */ #include <linux/cpuset.h> /* * Default limits for DL period; on the top end we guard against small util * tasks still getting ridiculously long effective runtimes, on the bottom end we * guard against timer DoS. */ static unsigned int sysctl_sched_dl_period_max = …; /* ~4 seconds */ static unsigned int sysctl_sched_dl_period_min = …; /* 100 us */ #ifdef CONFIG_SYSCTL static struct ctl_table sched_dl_sysctls[] = …; static int __init sched_dl_sysctl_init(void) { … } late_initcall(sched_dl_sysctl_init); #endif static bool dl_server(struct sched_dl_entity *dl_se) { … } static inline struct task_struct *dl_task_of(struct sched_dl_entity *dl_se) { … } static inline struct rq *rq_of_dl_rq(struct dl_rq *dl_rq) { … } static inline struct rq *rq_of_dl_se(struct sched_dl_entity *dl_se) { … } static inline struct dl_rq *dl_rq_of_se(struct sched_dl_entity *dl_se) { … } static inline int on_dl_rq(struct sched_dl_entity *dl_se) { … } #ifdef CONFIG_RT_MUTEXES static inline struct sched_dl_entity *pi_of(struct sched_dl_entity *dl_se) { … } static inline bool is_dl_boosted(struct sched_dl_entity *dl_se) { … } #else static inline struct sched_dl_entity *pi_of(struct sched_dl_entity *dl_se) { return dl_se; } static inline bool is_dl_boosted(struct sched_dl_entity *dl_se) { return false; } #endif #ifdef CONFIG_SMP static inline struct dl_bw *dl_bw_of(int i) { … } static inline int dl_bw_cpus(int i) { … } static inline unsigned long __dl_bw_capacity(const struct cpumask *mask) { … } /* * XXX Fix: If 'rq->rd == def_root_domain' perform AC against capacity * of the CPU the task is running on rather rd's \Sum CPU capacity. */ static inline unsigned long dl_bw_capacity(int i) { … } static inline bool dl_bw_visited(int cpu, u64 gen) { … } static inline void __dl_update(struct dl_bw *dl_b, s64 bw) { … } #else static inline struct dl_bw *dl_bw_of(int i) { return &cpu_rq(i)->dl.dl_bw; } static inline int dl_bw_cpus(int i) { return 1; } static inline unsigned long dl_bw_capacity(int i) { return SCHED_CAPACITY_SCALE; } static inline bool dl_bw_visited(int cpu, u64 gen) { return false; } static inline void __dl_update(struct dl_bw *dl_b, s64 bw) { struct dl_rq *dl = container_of(dl_b, struct dl_rq, dl_bw); dl->extra_bw += bw; } #endif static inline void __dl_sub(struct dl_bw *dl_b, u64 tsk_bw, int cpus) { … } static inline void __dl_add(struct dl_bw *dl_b, u64 tsk_bw, int cpus) { … } static inline bool __dl_overflow(struct dl_bw *dl_b, unsigned long cap, u64 old_bw, u64 new_bw) { … } static inline void __add_running_bw(u64 dl_bw, struct dl_rq *dl_rq) { … } static inline void __sub_running_bw(u64 dl_bw, struct dl_rq *dl_rq) { … } static inline void __add_rq_bw(u64 dl_bw, struct dl_rq *dl_rq) { … } static inline void __sub_rq_bw(u64 dl_bw, struct dl_rq *dl_rq) { … } static inline void add_rq_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static inline void sub_rq_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static inline void add_running_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static inline void sub_running_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static void dl_change_utilization(struct task_struct *p, u64 new_bw) { … } static void __dl_clear_params(struct sched_dl_entity *dl_se); /* * The utilization of a task cannot be immediately removed from * the rq active utilization (running_bw) when the task blocks. * Instead, we have to wait for the so called "0-lag time". * * If a task blocks before the "0-lag time", a timer (the inactive * timer) is armed, and running_bw is decreased when the timer * fires. * * If the task wakes up again before the inactive timer fires, * the timer is canceled, whereas if the task wakes up after the * inactive timer fired (and running_bw has been decreased) the * task's utilization has to be added to running_bw again. * A flag in the deadline scheduling entity (dl_non_contending) * is used to avoid race conditions between the inactive timer handler * and task wakeups. * * The following diagram shows how running_bw is updated. A task is * "ACTIVE" when its utilization contributes to running_bw; an * "ACTIVE contending" task is in the TASK_RUNNING state, while an * "ACTIVE non contending" task is a blocked task for which the "0-lag time" * has not passed yet. An "INACTIVE" task is a task for which the "0-lag" * time already passed, which does not contribute to running_bw anymore. * +------------------+ * wakeup | ACTIVE | * +------------------>+ contending | * | add_running_bw | | * | +----+------+------+ * | | ^ * | dequeue | | * +--------+-------+ | | * | | t >= 0-lag | | wakeup * | INACTIVE |<---------------+ | * | | sub_running_bw | | * +--------+-------+ | | * ^ | | * | t < 0-lag | | * | | | * | V | * | +----+------+------+ * | sub_running_bw | ACTIVE | * +-------------------+ | * inactive timer | non contending | * fired +------------------+ * * The task_non_contending() function is invoked when a task * blocks, and checks if the 0-lag time already passed or * not (in the first case, it directly updates running_bw; * in the second case, it arms the inactive timer). * * The task_contending() function is invoked when a task wakes * up, and checks if the task is still in the "ACTIVE non contending" * state or not (in the second case, it updates running_bw). */ static void task_non_contending(struct sched_dl_entity *dl_se) { … } static void task_contending(struct sched_dl_entity *dl_se, int flags) { … } static inline int is_leftmost(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static void init_dl_rq_bw_ratio(struct dl_rq *dl_rq); void init_dl_bw(struct dl_bw *dl_b) { … } void init_dl_rq(struct dl_rq *dl_rq) { … } #ifdef CONFIG_SMP static inline int dl_overloaded(struct rq *rq) { … } static inline void dl_set_overload(struct rq *rq) { … } static inline void dl_clear_overload(struct rq *rq) { … } #define __node_2_pdl(node) … static inline bool __pushable_less(struct rb_node *a, const struct rb_node *b) { … } static inline int has_pushable_dl_tasks(struct rq *rq) { … } /* * The list of pushable -deadline task is not a plist, like in * sched_rt.c, it is an rb-tree with tasks ordered by deadline. */ static void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p) { … } static void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p) { … } static int push_dl_task(struct rq *rq); static inline bool need_pull_dl_task(struct rq *rq, struct task_struct *prev) { … } static DEFINE_PER_CPU(struct balance_callback, dl_push_head); static DEFINE_PER_CPU(struct balance_callback, dl_pull_head); static void push_dl_tasks(struct rq *); static void pull_dl_task(struct rq *); static inline void deadline_queue_push_tasks(struct rq *rq) { … } static inline void deadline_queue_pull_task(struct rq *rq) { … } static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq); static struct rq *dl_task_offline_migration(struct rq *rq, struct task_struct *p) { … } #else static inline void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p) { } static inline void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p) { } static inline void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { } static inline void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { } static inline void deadline_queue_push_tasks(struct rq *rq) { } static inline void deadline_queue_pull_task(struct rq *rq) { } #endif /* CONFIG_SMP */ static void enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags); static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags); static void dequeue_dl_entity(struct sched_dl_entity *dl_se, int flags); static void wakeup_preempt_dl(struct rq *rq, struct task_struct *p, int flags); static inline void replenish_dl_new_period(struct sched_dl_entity *dl_se, struct rq *rq) { … } /* * We are being explicitly informed that a new instance is starting, * and this means that: * - the absolute deadline of the entity has to be placed at * current time + relative deadline; * - the runtime of the entity has to be set to the maximum value. * * The capability of specifying such event is useful whenever a -deadline * entity wants to (try to!) synchronize its behaviour with the scheduler's * one, and to (try to!) reconcile itself with its own scheduling * parameters. */ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se) { … } /* * Pure Earliest Deadline First (EDF) scheduling does not deal with the * possibility of a entity lasting more than what it declared, and thus * exhausting its runtime. * * Here we are interested in making runtime overrun possible, but we do * not want a entity which is misbehaving to affect the scheduling of all * other entities. * Therefore, a budgeting strategy called Constant Bandwidth Server (CBS) * is used, in order to confine each entity within its own bandwidth. * * This function deals exactly with that, and ensures that when the runtime * of a entity is replenished, its deadline is also postponed. That ensures * the overrunning entity can't interfere with other entity in the system and * can't make them miss their deadlines. Reasons why this kind of overruns * could happen are, typically, a entity voluntarily trying to overcome its * runtime, or it just underestimated it during sched_setattr(). */ static void replenish_dl_entity(struct sched_dl_entity *dl_se) { … } /* * Here we check if --at time t-- an entity (which is probably being * [re]activated or, in general, enqueued) can use its remaining runtime * and its current deadline _without_ exceeding the bandwidth it is * assigned (function returns true if it can't). We are in fact applying * one of the CBS rules: when a task wakes up, if the residual runtime * over residual deadline fits within the allocated bandwidth, then we * can keep the current (absolute) deadline and residual budget without * disrupting the schedulability of the system. Otherwise, we should * refill the runtime and set the deadline a period in the future, * because keeping the current (absolute) deadline of the task would * result in breaking guarantees promised to other tasks (refer to * Documentation/scheduler/sched-deadline.rst for more information). * * This function returns true if: * * runtime / (deadline - t) > dl_runtime / dl_deadline , * * IOW we can't recycle current parameters. * * Notice that the bandwidth check is done against the deadline. For * task with deadline equal to period this is the same of using * dl_period instead of dl_deadline in the equation above. */ static bool dl_entity_overflow(struct sched_dl_entity *dl_se, u64 t) { … } /* * Revised wakeup rule [1]: For self-suspending tasks, rather then * re-initializing task's runtime and deadline, the revised wakeup * rule adjusts the task's runtime to avoid the task to overrun its * density. * * Reasoning: a task may overrun the density if: * runtime / (deadline - t) > dl_runtime / dl_deadline * * Therefore, runtime can be adjusted to: * runtime = (dl_runtime / dl_deadline) * (deadline - t) * * In such way that runtime will be equal to the maximum density * the task can use without breaking any rule. * * [1] Luca Abeni, Giuseppe Lipari, and Juri Lelli. 2015. Constant * bandwidth server revisited. SIGBED Rev. 11, 4 (January 2015), 19-24. */ static void update_dl_revised_wakeup(struct sched_dl_entity *dl_se, struct rq *rq) { … } /* * Regarding the deadline, a task with implicit deadline has a relative * deadline == relative period. A task with constrained deadline has a * relative deadline <= relative period. * * We support constrained deadline tasks. However, there are some restrictions * applied only for tasks which do not have an implicit deadline. See * update_dl_entity() to know more about such restrictions. * * The dl_is_implicit() returns true if the task has an implicit deadline. */ static inline bool dl_is_implicit(struct sched_dl_entity *dl_se) { … } /* * When a deadline entity is placed in the runqueue, its runtime and deadline * might need to be updated. This is done by a CBS wake up rule. There are two * different rules: 1) the original CBS; and 2) the Revisited CBS. * * When the task is starting a new period, the Original CBS is used. In this * case, the runtime is replenished and a new absolute deadline is set. * * When a task is queued before the begin of the next period, using the * remaining runtime and deadline could make the entity to overflow, see * dl_entity_overflow() to find more about runtime overflow. When such case * is detected, the runtime and deadline need to be updated. * * If the task has an implicit deadline, i.e., deadline == period, the Original * CBS is applied. The runtime is replenished and a new absolute deadline is * set, as in the previous cases. * * However, the Original CBS does not work properly for tasks with * deadline < period, which are said to have a constrained deadline. By * applying the Original CBS, a constrained deadline task would be able to run * runtime/deadline in a period. With deadline < period, the task would * overrun the runtime/period allowed bandwidth, breaking the admission test. * * In order to prevent this misbehave, the Revisited CBS is used for * constrained deadline tasks when a runtime overflow is detected. In the * Revisited CBS, rather than replenishing & setting a new absolute deadline, * the remaining runtime of the task is reduced to avoid runtime overflow. * Please refer to the comments update_dl_revised_wakeup() function to find * more about the Revised CBS rule. */ static void update_dl_entity(struct sched_dl_entity *dl_se) { … } static inline u64 dl_next_period(struct sched_dl_entity *dl_se) { … } /* * If the entity depleted all its runtime, and if we want it to sleep * while waiting for some new execution time to become available, we * set the bandwidth replenishment timer to the replenishment instant * and try to activate it. * * Notice that it is important for the caller to know if the timer * actually started or not (i.e., the replenishment instant is in * the future or in the past). */ static int start_dl_timer(struct sched_dl_entity *dl_se) { … } static void __push_dl_task(struct rq *rq, struct rq_flags *rf) { … } /* * This is the bandwidth enforcement timer callback. If here, we know * a task is not on its dl_rq, since the fact that the timer was running * means the task is throttled and needs a runtime replenishment. * * However, what we actually do depends on the fact the task is active, * (it is on its rq) or has been removed from there by a call to * dequeue_task_dl(). In the former case we must issue the runtime * replenishment and add the task back to the dl_rq; in the latter, we just * do nothing but clearing dl_throttled, so that runtime and deadline * updating (and the queueing back to dl_rq) will be done by the * next call to enqueue_task_dl(). */ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) { … } static void init_dl_task_timer(struct sched_dl_entity *dl_se) { … } /* * During the activation, CBS checks if it can reuse the current task's * runtime and period. If the deadline of the task is in the past, CBS * cannot use the runtime, and so it replenishes the task. This rule * works fine for implicit deadline tasks (deadline == period), and the * CBS was designed for implicit deadline tasks. However, a task with * constrained deadline (deadline < period) might be awakened after the * deadline, but before the next period. In this case, replenishing the * task would allow it to run for runtime / deadline. As in this case * deadline < period, CBS enables a task to run for more than the * runtime / period. In a very loaded system, this can cause a domino * effect, making other tasks miss their deadlines. * * To avoid this problem, in the activation of a constrained deadline * task after the deadline but before the next period, throttle the * task and set the replenishing timer to the begin of the next period, * unless it is boosted. */ static inline void dl_check_constrained_dl(struct sched_dl_entity *dl_se) { … } static int dl_runtime_exceeded(struct sched_dl_entity *dl_se) { … } /* * This function implements the GRUB accounting rule. According to the * GRUB reclaiming algorithm, the runtime is not decreased as "dq = -dt", * but as "dq = -(max{u, (Umax - Uinact - Uextra)} / Umax) dt", * where u is the utilization of the task, Umax is the maximum reclaimable * utilization, Uinact is the (per-runqueue) inactive utilization, computed * as the difference between the "total runqueue utilization" and the * "runqueue active utilization", and Uextra is the (per runqueue) extra * reclaimable utilization. * Since rq->dl.running_bw and rq->dl.this_bw contain utilizations multiplied * by 2^BW_SHIFT, the result has to be shifted right by BW_SHIFT. * Since rq->dl.bw_ratio contains 1 / Umax multiplied by 2^RATIO_SHIFT, dl_bw * is multiplied by rq->dl.bw_ratio and shifted right by RATIO_SHIFT. * Since delta is a 64 bit variable, to have an overflow its value should be * larger than 2^(64 - 20 - 8), which is more than 64 seconds. So, overflow is * not an issue here. */ static u64 grub_reclaim(u64 delta, struct rq *rq, struct sched_dl_entity *dl_se) { … } static inline void update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int flags); static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 delta_exec) { … } void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec) { … } void dl_server_start(struct sched_dl_entity *dl_se) { … } void dl_server_stop(struct sched_dl_entity *dl_se) { … } void dl_server_init(struct sched_dl_entity *dl_se, struct rq *rq, dl_server_has_tasks_f has_tasks, dl_server_pick_f pick) { … } /* * Update the current task's runtime statistics (provided it is still * a -deadline task and has not been removed from the dl_rq). */ static void update_curr_dl(struct rq *rq) { … } static enum hrtimer_restart inactive_task_timer(struct hrtimer *timer) { … } static void init_dl_inactive_task_timer(struct sched_dl_entity *dl_se) { … } #define __node_2_dle(node) … #ifdef CONFIG_SMP static void inc_dl_deadline(struct dl_rq *dl_rq, u64 deadline) { … } static void dec_dl_deadline(struct dl_rq *dl_rq, u64 deadline) { … } #else static inline void inc_dl_deadline(struct dl_rq *dl_rq, u64 deadline) {} static inline void dec_dl_deadline(struct dl_rq *dl_rq, u64 deadline) {} #endif /* CONFIG_SMP */ static inline void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static inline void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { … } static inline bool __dl_less(struct rb_node *a, const struct rb_node *b) { … } static inline struct sched_statistics * __schedstats_from_dl_se(struct sched_dl_entity *dl_se) { … } static inline void update_stats_wait_start_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se) { … } static inline void update_stats_wait_end_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se) { … } static inline void update_stats_enqueue_sleeper_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se) { … } static inline void update_stats_enqueue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int flags) { … } static inline void update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int flags) { … } static void __enqueue_dl_entity(struct sched_dl_entity *dl_se) { … } static void __dequeue_dl_entity(struct sched_dl_entity *dl_se) { … } static void enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags) { … } static void dequeue_dl_entity(struct sched_dl_entity *dl_se, int flags) { … } static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) { … } static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { … } /* * Yield task semantic for -deadline tasks is: * * get off from the CPU until our next instance, with * a new runtime. This is of little use now, since we * don't have a bandwidth reclaiming mechanism. Anyway, * bandwidth reclaiming is planned for the future, and * yield_task_dl will indicate that some spare budget * is available for other task instances to use it. */ static void yield_task_dl(struct rq *rq) { … } #ifdef CONFIG_SMP static inline bool dl_task_is_earliest_deadline(struct task_struct *p, struct rq *rq) { … } static int find_later_rq(struct task_struct *task); static int select_task_rq_dl(struct task_struct *p, int cpu, int flags) { … } static void migrate_task_rq_dl(struct task_struct *p, int new_cpu __maybe_unused) { … } static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p) { … } static int balance_dl(struct rq *rq, struct task_struct *p, struct rq_flags *rf) { … } #endif /* CONFIG_SMP */ /* * Only called when both the current and waking task are -deadline * tasks. */ static void wakeup_preempt_dl(struct rq *rq, struct task_struct *p, int flags) { … } #ifdef CONFIG_SCHED_HRTICK static void start_hrtick_dl(struct rq *rq, struct sched_dl_entity *dl_se) { … } #else /* !CONFIG_SCHED_HRTICK */ static void start_hrtick_dl(struct rq *rq, struct sched_dl_entity *dl_se) { } #endif static void set_next_task_dl(struct rq *rq, struct task_struct *p, bool first) { … } static struct sched_dl_entity *pick_next_dl_entity(struct dl_rq *dl_rq) { … } static struct task_struct *pick_task_dl(struct rq *rq) { … } static struct task_struct *pick_next_task_dl(struct rq *rq) { … } static void put_prev_task_dl(struct rq *rq, struct task_struct *p) { … } /* * scheduler tick hitting a task of our scheduling class. * * NOTE: This function can be called remotely by the tick offload that * goes along full dynticks. Therefore no local assumption can be made * and everything must be accessed through the @rq and @curr passed in * parameters. */ static void task_tick_dl(struct rq *rq, struct task_struct *p, int queued) { … } static void task_fork_dl(struct task_struct *p) { … } #ifdef CONFIG_SMP /* Only try algorithms three times */ #define DL_MAX_TRIES … static int pick_dl_task(struct rq *rq, struct task_struct *p, int cpu) { … } /* * Return the earliest pushable rq's task, which is suitable to be executed * on the CPU, NULL otherwise: */ static struct task_struct *pick_earliest_pushable_dl_task(struct rq *rq, int cpu) { … } static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask_dl); static int find_later_rq(struct task_struct *task) { … } /* Locks the rq it finds */ static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq) { … } static struct task_struct *pick_next_pushable_dl_task(struct rq *rq) { … } /* * See if the non running -deadline tasks on this rq * can be sent to some other CPU where they can preempt * and start executing. */ static int push_dl_task(struct rq *rq) { … } static void push_dl_tasks(struct rq *rq) { … } static void pull_dl_task(struct rq *this_rq) { … } /* * Since the task is not running and a reschedule is not going to happen * anytime soon on its runqueue, we try pushing it away now. */ static void task_woken_dl(struct rq *rq, struct task_struct *p) { … } static void set_cpus_allowed_dl(struct task_struct *p, struct affinity_context *ctx) { … } /* Assumes rq->lock is held */ static void rq_online_dl(struct rq *rq) { … } /* Assumes rq->lock is held */ static void rq_offline_dl(struct rq *rq) { … } void __init init_sched_dl_class(void) { … } void dl_add_task_root_domain(struct task_struct *p) { … } void dl_clear_root_domain(struct root_domain *rd) { … } #endif /* CONFIG_SMP */ static void switched_from_dl(struct rq *rq, struct task_struct *p) { … } /* * When switching to -deadline, we may overload the rq, then * we try to push someone off, if possible. */ static void switched_to_dl(struct rq *rq, struct task_struct *p) { … } /* * If the scheduling parameters of a -deadline task changed, * a push or pull operation might be needed. */ static void prio_changed_dl(struct rq *rq, struct task_struct *p, int oldprio) { … } #ifdef CONFIG_SCHED_CORE static int task_is_throttled_dl(struct task_struct *p, int cpu) { … } #endif DEFINE_SCHED_CLASS(dl) = …; /* Used for dl_bw check and update, used under sched_rt_handler()::mutex */ static u64 dl_generation; int sched_dl_global_validate(void) { … } static void init_dl_rq_bw_ratio(struct dl_rq *dl_rq) { … } void sched_dl_do_global(void) { … } /* * We must be sure that accepting a new task (or allowing changing the * parameters of an existing one) is consistent with the bandwidth * constraints. If yes, this function also accordingly updates the currently * allocated bandwidth to reflect the new situation. * * This function is called while holding p's rq->lock. */ int sched_dl_overflow(struct task_struct *p, int policy, const struct sched_attr *attr) { … } /* * This function initializes the sched_dl_entity of a newly becoming * SCHED_DEADLINE task. * * Only the static values are considered here, the actual runtime and the * absolute deadline will be properly calculated when the task is enqueued * for the first time with its new policy. */ void __setparam_dl(struct task_struct *p, const struct sched_attr *attr) { … } void __getparam_dl(struct task_struct *p, struct sched_attr *attr) { … } /* * This function validates the new parameters of a -deadline task. * We ask for the deadline not being zero, and greater or equal * than the runtime, as well as the period of being zero or * greater than deadline. Furthermore, we have to be sure that * user parameters are above the internal resolution of 1us (we * check sched_runtime only since it is always the smaller one) and * below 2^63 ns (we have to check both sched_deadline and * sched_period, as the latter can be zero). */ bool __checkparam_dl(const struct sched_attr *attr) { … } /* * This function clears the sched_dl_entity static params. */ static void __dl_clear_params(struct sched_dl_entity *dl_se) { … } void init_dl_entity(struct sched_dl_entity *dl_se) { … } bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr) { … } #ifdef CONFIG_SMP int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial) { … } enum dl_bw_request { … }; static int dl_bw_manage(enum dl_bw_request req, int cpu, u64 dl_bw) { … } int dl_bw_check_overflow(int cpu) { … } int dl_bw_alloc(int cpu, u64 dl_bw) { … } void dl_bw_free(int cpu, u64 dl_bw) { … } #endif #ifdef CONFIG_SCHED_DEBUG void print_dl_stats(struct seq_file *m, int cpu) { … } #endif /* CONFIG_SCHED_DEBUG */