aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2017-06-21 14:22:01 -0400
committerIngo Molnar <mingo@kernel.org>2017-06-23 04:46:45 -0400
commit06a76fe08d4daaeea01ca0f175ad29f40c781ece (patch)
tree241c0de99295286aa65d55766129c30a1be955c6
parente1d4eeec5aaa28d25f249c0195b0e1d9b9feb7bd (diff)
sched/deadline: Move DL related code from sched/core.c to sched/deadline.c
This helps making sched/core.c smaller and hopefully easier to understand and maintain. Signed-off-by: Nicolas Pitre <nico@linaro.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20170621182203.30626-2-nicolas.pitre@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/sched/core.c343
-rw-r--r--kernel/sched/deadline.c344
-rw-r--r--kernel/sched/sched.h17
3 files changed, 364 insertions, 340 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7faf4b322b63..54e1b0700af3 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2140,25 +2140,6 @@ int wake_up_state(struct task_struct *p, unsigned int state)
2140} 2140}
2141 2141
2142/* 2142/*
2143 * This function clears the sched_dl_entity static params.
2144 */
2145void __dl_clear_params(struct task_struct *p)
2146{
2147 struct sched_dl_entity *dl_se = &p->dl;
2148
2149 dl_se->dl_runtime = 0;
2150 dl_se->dl_deadline = 0;
2151 dl_se->dl_period = 0;
2152 dl_se->flags = 0;
2153 dl_se->dl_bw = 0;
2154 dl_se->dl_density = 0;
2155
2156 dl_se->dl_throttled = 0;
2157 dl_se->dl_yielded = 0;
2158 dl_se->dl_non_contending = 0;
2159}
2160
2161/*
2162 * Perform scheduler related setup for a newly forked process p. 2143 * Perform scheduler related setup for a newly forked process p.
2163 * p is forked by current. 2144 * p is forked by current.
2164 * 2145 *
@@ -2438,101 +2419,6 @@ unsigned long to_ratio(u64 period, u64 runtime)
2438 return div64_u64(runtime << BW_SHIFT, period); 2419 return div64_u64(runtime << BW_SHIFT, period);
2439} 2420}
2440 2421
2441#ifdef CONFIG_SMP
2442inline struct dl_bw *dl_bw_of(int i)
2443{
2444 RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
2445 "sched RCU must be held");
2446 return &cpu_rq(i)->rd->dl_bw;
2447}
2448
2449inline int dl_bw_cpus(int i)
2450{
2451 struct root_domain *rd = cpu_rq(i)->rd;
2452 int cpus = 0;
2453
2454 RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
2455 "sched RCU must be held");
2456 for_each_cpu_and(i, rd->span, cpu_active_mask)
2457 cpus++;
2458
2459 return cpus;
2460}
2461#else
2462inline struct dl_bw *dl_bw_of(int i)
2463{
2464 return &cpu_rq(i)->dl.dl_bw;
2465}
2466
2467inline int dl_bw_cpus(int i)
2468{
2469 return 1;
2470}
2471#endif
2472
2473/*
2474 * We must be sure that accepting a new task (or allowing changing the
2475 * parameters of an existing one) is consistent with the bandwidth
2476 * constraints. If yes, this function also accordingly updates the currently
2477 * allocated bandwidth to reflect the new situation.
2478 *
2479 * This function is called while holding p's rq->lock.
2480 */
2481static int dl_overflow(struct task_struct *p, int policy,
2482 const struct sched_attr *attr)
2483{
2484
2485 struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
2486 u64 period = attr->sched_period ?: attr->sched_deadline;
2487 u64 runtime = attr->sched_runtime;
2488 u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
2489 int cpus, err = -1;
2490
2491 /* !deadline task may carry old deadline bandwidth */
2492 if (new_bw == p->dl.dl_bw && task_has_dl_policy(p))
2493 return 0;
2494
2495 /*
2496 * Either if a task, enters, leave, or stays -deadline but changes
2497 * its parameters, we may need to update accordingly the total
2498 * allocated bandwidth of the container.
2499 */
2500 raw_spin_lock(&dl_b->lock);
2501 cpus = dl_bw_cpus(task_cpu(p));
2502 if (dl_policy(policy) && !task_has_dl_policy(p) &&
2503 !__dl_overflow(dl_b, cpus, 0, new_bw)) {
2504 if (hrtimer_active(&p->dl.inactive_timer))
2505 __dl_clear(dl_b, p->dl.dl_bw, cpus);
2506 __dl_add(dl_b, new_bw, cpus);
2507 err = 0;
2508 } else if (dl_policy(policy) && task_has_dl_policy(p) &&
2509 !__dl_overflow(dl_b, cpus, p->dl.dl_bw, new_bw)) {
2510 /*
2511 * XXX this is slightly incorrect: when the task
2512 * utilization decreases, we should delay the total
2513 * utilization change until the task's 0-lag point.
2514 * But this would require to set the task's "inactive
2515 * timer" when the task is not inactive.
2516 */
2517 __dl_clear(dl_b, p->dl.dl_bw, cpus);
2518 __dl_add(dl_b, new_bw, cpus);
2519 dl_change_utilization(p, new_bw);
2520 err = 0;
2521 } else if (!dl_policy(policy) && task_has_dl_policy(p)) {
2522 /*
2523 * Do not decrease the total deadline utilization here,
2524 * switched_from_dl() will take care to do it at the correct
2525 * (0-lag) time.
2526 */
2527 err = 0;
2528 }
2529 raw_spin_unlock(&dl_b->lock);
2530
2531 return err;
2532}
2533
2534extern void init_dl_bw(struct dl_bw *dl_b);
2535
2536/* 2422/*
2537 * wake_up_new_task - wake up a newly created task for the first time. 2423 * wake_up_new_task - wake up a newly created task for the first time.
2538 * 2424 *
@@ -4015,27 +3901,6 @@ static struct task_struct *find_process_by_pid(pid_t pid)
4015} 3901}
4016 3902
4017/* 3903/*
4018 * This function initializes the sched_dl_entity of a newly becoming
4019 * SCHED_DEADLINE task.
4020 *
4021 * Only the static values are considered here, the actual runtime and the
4022 * absolute deadline will be properly calculated when the task is enqueued
4023 * for the first time with its new policy.
4024 */
4025static void
4026__setparam_dl(struct task_struct *p, const struct sched_attr *attr)
4027{
4028 struct sched_dl_entity *dl_se = &p->dl;
4029
4030 dl_se->dl_runtime = attr->sched_runtime;
4031 dl_se->dl_deadline = attr->sched_deadline;
4032 dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline;
4033 dl_se->flags = attr->sched_flags;
4034 dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
4035 dl_se->dl_density = to_ratio(dl_se->dl_deadline, dl_se->dl_runtime);
4036}
4037
4038/*
4039 * sched_setparam() passes in -1 for its policy, to let the functions 3904 * sched_setparam() passes in -1 for its policy, to let the functions
4040 * it calls know not to change it. 3905 * it calls know not to change it.
4041 */ 3906 */
@@ -4088,59 +3953,6 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
4088 p->sched_class = &fair_sched_class; 3953 p->sched_class = &fair_sched_class;
4089} 3954}
4090 3955
4091static void
4092__getparam_dl(struct task_struct *p, struct sched_attr *attr)
4093{
4094 struct sched_dl_entity *dl_se = &p->dl;
4095
4096 attr->sched_priority = p->rt_priority;
4097 attr->sched_runtime = dl_se->dl_runtime;
4098 attr->sched_deadline = dl_se->dl_deadline;
4099 attr->sched_period = dl_se->dl_period;
4100 attr->sched_flags = dl_se->flags;
4101}
4102
4103/*
4104 * This function validates the new parameters of a -deadline task.
4105 * We ask for the deadline not being zero, and greater or equal
4106 * than the runtime, as well as the period of being zero or
4107 * greater than deadline. Furthermore, we have to be sure that
4108 * user parameters are above the internal resolution of 1us (we
4109 * check sched_runtime only since it is always the smaller one) and
4110 * below 2^63 ns (we have to check both sched_deadline and
4111 * sched_period, as the latter can be zero).
4112 */
4113static bool
4114__checkparam_dl(const struct sched_attr *attr)
4115{
4116 /* deadline != 0 */
4117 if (attr->sched_deadline == 0)
4118 return false;
4119
4120 /*
4121 * Since we truncate DL_SCALE bits, make sure we're at least
4122 * that big.
4123 */
4124 if (attr->sched_runtime < (1ULL << DL_SCALE))
4125 return false;
4126
4127 /*
4128 * Since we use the MSB for wrap-around and sign issues, make
4129 * sure it's not set (mind that period can be equal to zero).
4130 */
4131 if (attr->sched_deadline & (1ULL << 63) ||
4132 attr->sched_period & (1ULL << 63))
4133 return false;
4134
4135 /* runtime <= deadline <= period (if period != 0) */
4136 if ((attr->sched_period != 0 &&
4137 attr->sched_period < attr->sched_deadline) ||
4138 attr->sched_deadline < attr->sched_runtime)
4139 return false;
4140
4141 return true;
4142}
4143
4144/* 3956/*
4145 * Check the target process has a UID that matches the current process's: 3957 * Check the target process has a UID that matches the current process's:
4146 */ 3958 */
@@ -4157,19 +3969,6 @@ static bool check_same_owner(struct task_struct *p)
4157 return match; 3969 return match;
4158} 3970}
4159 3971
4160static bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
4161{
4162 struct sched_dl_entity *dl_se = &p->dl;
4163
4164 if (dl_se->dl_runtime != attr->sched_runtime ||
4165 dl_se->dl_deadline != attr->sched_deadline ||
4166 dl_se->dl_period != attr->sched_period ||
4167 dl_se->flags != attr->sched_flags)
4168 return true;
4169
4170 return false;
4171}
4172
4173static int __sched_setscheduler(struct task_struct *p, 3972static int __sched_setscheduler(struct task_struct *p,
4174 const struct sched_attr *attr, 3973 const struct sched_attr *attr,
4175 bool user, bool pi) 3974 bool user, bool pi)
@@ -4350,7 +4149,7 @@ change:
4350 * of a SCHED_DEADLINE task) we need to check if enough bandwidth 4149 * of a SCHED_DEADLINE task) we need to check if enough bandwidth
4351 * is available. 4150 * is available.
4352 */ 4151 */
4353 if ((dl_policy(policy) || dl_task(p)) && dl_overflow(p, policy, attr)) { 4152 if ((dl_policy(policy) || dl_task(p)) && sched_dl_overflow(p, policy, attr)) {
4354 task_rq_unlock(rq, p, &rf); 4153 task_rq_unlock(rq, p, &rf);
4355 return -EBUSY; 4154 return -EBUSY;
4356 } 4155 }
@@ -5456,23 +5255,12 @@ void init_idle(struct task_struct *idle, int cpu)
5456int cpuset_cpumask_can_shrink(const struct cpumask *cur, 5255int cpuset_cpumask_can_shrink(const struct cpumask *cur,
5457 const struct cpumask *trial) 5256 const struct cpumask *trial)
5458{ 5257{
5459 int ret = 1, trial_cpus; 5258 int ret = 1;
5460 struct dl_bw *cur_dl_b;
5461 unsigned long flags;
5462 5259
5463 if (!cpumask_weight(cur)) 5260 if (!cpumask_weight(cur))
5464 return ret; 5261 return ret;
5465 5262
5466 rcu_read_lock_sched(); 5263 ret = dl_cpuset_cpumask_can_shrink(cur, trial);
5467 cur_dl_b = dl_bw_of(cpumask_any(cur));
5468 trial_cpus = cpumask_weight(trial);
5469
5470 raw_spin_lock_irqsave(&cur_dl_b->lock, flags);
5471 if (cur_dl_b->bw != -1 &&
5472 cur_dl_b->bw * trial_cpus < cur_dl_b->total_bw)
5473 ret = 0;
5474 raw_spin_unlock_irqrestore(&cur_dl_b->lock, flags);
5475 rcu_read_unlock_sched();
5476 5264
5477 return ret; 5265 return ret;
5478} 5266}
@@ -5497,34 +5285,8 @@ int task_can_attach(struct task_struct *p,
5497 } 5285 }
5498 5286
5499 if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span, 5287 if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
5500 cs_cpus_allowed)) { 5288 cs_cpus_allowed))
5501 unsigned int dest_cpu = cpumask_any_and(cpu_active_mask, 5289 ret = dl_task_can_attach(p, cs_cpus_allowed);
5502 cs_cpus_allowed);
5503 struct dl_bw *dl_b;
5504 bool overflow;
5505 int cpus;
5506 unsigned long flags;
5507
5508 rcu_read_lock_sched();
5509 dl_b = dl_bw_of(dest_cpu);
5510 raw_spin_lock_irqsave(&dl_b->lock, flags);
5511 cpus = dl_bw_cpus(dest_cpu);
5512 overflow = __dl_overflow(dl_b, cpus, 0, p->dl.dl_bw);
5513 if (overflow)
5514 ret = -EBUSY;
5515 else {
5516 /*
5517 * We reserve space for this task in the destination
5518 * root_domain, as we can't fail after this point.
5519 * We will free resources in the source root_domain
5520 * later on (see set_cpus_allowed_dl()).
5521 */
5522 __dl_add(dl_b, p->dl.dl_bw, cpus);
5523 }
5524 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
5525 rcu_read_unlock_sched();
5526
5527 }
5528 5290
5529out: 5291out:
5530 return ret; 5292 return ret;
@@ -5792,23 +5554,8 @@ static void cpuset_cpu_active(void)
5792 5554
5793static int cpuset_cpu_inactive(unsigned int cpu) 5555static int cpuset_cpu_inactive(unsigned int cpu)
5794{ 5556{
5795 unsigned long flags;
5796 struct dl_bw *dl_b;
5797 bool overflow;
5798 int cpus;
5799
5800 if (!cpuhp_tasks_frozen) { 5557 if (!cpuhp_tasks_frozen) {
5801 rcu_read_lock_sched(); 5558 if (dl_cpu_busy(cpu))
5802 dl_b = dl_bw_of(cpu);
5803
5804 raw_spin_lock_irqsave(&dl_b->lock, flags);
5805 cpus = dl_bw_cpus(cpu);
5806 overflow = __dl_overflow(dl_b, cpus, 0, 0);
5807 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
5808
5809 rcu_read_unlock_sched();
5810
5811 if (overflow)
5812 return -EBUSY; 5559 return -EBUSY;
5813 cpuset_update_active_cpus(); 5560 cpuset_update_active_cpus();
5814 } else { 5561 } else {
@@ -6711,84 +6458,6 @@ static int sched_rt_global_constraints(void)
6711} 6458}
6712#endif /* CONFIG_RT_GROUP_SCHED */ 6459#endif /* CONFIG_RT_GROUP_SCHED */
6713 6460
6714static int sched_dl_global_validate(void)
6715{
6716 u64 runtime = global_rt_runtime();
6717 u64 period = global_rt_period();
6718 u64 new_bw = to_ratio(period, runtime);
6719 struct dl_bw *dl_b;
6720 int cpu, ret = 0;
6721 unsigned long flags;
6722
6723 /*
6724 * Here we want to check the bandwidth not being set to some
6725 * value smaller than the currently allocated bandwidth in
6726 * any of the root_domains.
6727 *
6728 * FIXME: Cycling on all the CPUs is overdoing, but simpler than
6729 * cycling on root_domains... Discussion on different/better
6730 * solutions is welcome!
6731 */
6732 for_each_possible_cpu(cpu) {
6733 rcu_read_lock_sched();
6734 dl_b = dl_bw_of(cpu);
6735
6736 raw_spin_lock_irqsave(&dl_b->lock, flags);
6737 if (new_bw < dl_b->total_bw)
6738 ret = -EBUSY;
6739 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
6740
6741 rcu_read_unlock_sched();
6742
6743 if (ret)
6744 break;
6745 }
6746
6747 return ret;
6748}
6749
6750void init_dl_rq_bw_ratio(struct dl_rq *dl_rq)
6751{
6752 if (global_rt_runtime() == RUNTIME_INF) {
6753 dl_rq->bw_ratio = 1 << RATIO_SHIFT;
6754 dl_rq->extra_bw = 1 << BW_SHIFT;
6755 } else {
6756 dl_rq->bw_ratio = to_ratio(global_rt_runtime(),
6757 global_rt_period()) >> (BW_SHIFT - RATIO_SHIFT);
6758 dl_rq->extra_bw = to_ratio(global_rt_period(),
6759 global_rt_runtime());
6760 }
6761}
6762
6763static void sched_dl_do_global(void)
6764{
6765 u64 new_bw = -1;
6766 struct dl_bw *dl_b;
6767 int cpu;
6768 unsigned long flags;
6769
6770 def_dl_bandwidth.dl_period = global_rt_period();
6771 def_dl_bandwidth.dl_runtime = global_rt_runtime();
6772
6773 if (global_rt_runtime() != RUNTIME_INF)
6774 new_bw = to_ratio(global_rt_period(), global_rt_runtime());
6775
6776 /*
6777 * FIXME: As above...
6778 */
6779 for_each_possible_cpu(cpu) {
6780 rcu_read_lock_sched();
6781 dl_b = dl_bw_of(cpu);
6782
6783 raw_spin_lock_irqsave(&dl_b->lock, flags);
6784 dl_b->bw = new_bw;
6785 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
6786
6787 rcu_read_unlock_sched();
6788 init_dl_rq_bw_ratio(&cpu_rq(cpu)->dl);
6789 }
6790}
6791
6792static int sched_rt_global_validate(void) 6461static int sched_rt_global_validate(void)
6793{ 6462{
6794 if (sysctl_sched_rt_period <= 0) 6463 if (sysctl_sched_rt_period <= 0)
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index e12f85975857..a84299f44b5d 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -17,6 +17,7 @@
17#include "sched.h" 17#include "sched.h"
18 18
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <uapi/linux/sched/types.h>
20 21
21struct dl_bandwidth def_dl_bandwidth; 22struct dl_bandwidth def_dl_bandwidth;
22 23
@@ -43,6 +44,38 @@ static inline int on_dl_rq(struct sched_dl_entity *dl_se)
43 return !RB_EMPTY_NODE(&dl_se->rb_node); 44 return !RB_EMPTY_NODE(&dl_se->rb_node);
44} 45}
45 46
47#ifdef CONFIG_SMP
48static inline struct dl_bw *dl_bw_of(int i)
49{
50 RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
51 "sched RCU must be held");
52 return &cpu_rq(i)->rd->dl_bw;
53}
54
55static inline int dl_bw_cpus(int i)
56{
57 struct root_domain *rd = cpu_rq(i)->rd;
58 int cpus = 0;
59
60 RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
61 "sched RCU must be held");
62 for_each_cpu_and(i, rd->span, cpu_active_mask)
63 cpus++;
64
65 return cpus;
66}
67#else
68static inline struct dl_bw *dl_bw_of(int i)
69{
70 return &cpu_rq(i)->dl.dl_bw;
71}
72
73static inline int dl_bw_cpus(int i)
74{
75 return 1;
76}
77#endif
78
46static inline 79static inline
47void add_running_bw(u64 dl_bw, struct dl_rq *dl_rq) 80void add_running_bw(u64 dl_bw, struct dl_rq *dl_rq)
48{ 81{
@@ -2318,6 +2351,317 @@ const struct sched_class dl_sched_class = {
2318 .update_curr = update_curr_dl, 2351 .update_curr = update_curr_dl,
2319}; 2352};
2320 2353
2354int sched_dl_global_validate(void)
2355{
2356 u64 runtime = global_rt_runtime();
2357 u64 period = global_rt_period();
2358 u64 new_bw = to_ratio(period, runtime);
2359 struct dl_bw *dl_b;
2360 int cpu, ret = 0;
2361 unsigned long flags;
2362
2363 /*
2364 * Here we want to check the bandwidth not being set to some
2365 * value smaller than the currently allocated bandwidth in
2366 * any of the root_domains.
2367 *
2368 * FIXME: Cycling on all the CPUs is overdoing, but simpler than
2369 * cycling on root_domains... Discussion on different/better
2370 * solutions is welcome!
2371 */
2372 for_each_possible_cpu(cpu) {
2373 rcu_read_lock_sched();
2374 dl_b = dl_bw_of(cpu);
2375
2376 raw_spin_lock_irqsave(&dl_b->lock, flags);
2377 if (new_bw < dl_b->total_bw)
2378 ret = -EBUSY;
2379 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
2380
2381 rcu_read_unlock_sched();
2382
2383 if (ret)
2384 break;
2385 }
2386
2387 return ret;
2388}
2389
2390void init_dl_rq_bw_ratio(struct dl_rq *dl_rq)
2391{
2392 if (global_rt_runtime() == RUNTIME_INF) {
2393 dl_rq->bw_ratio = 1 << RATIO_SHIFT;
2394 dl_rq->extra_bw = 1 << BW_SHIFT;
2395 } else {
2396 dl_rq->bw_ratio = to_ratio(global_rt_runtime(),
2397 global_rt_period()) >> (BW_SHIFT - RATIO_SHIFT);
2398 dl_rq->extra_bw = to_ratio(global_rt_period(),
2399 global_rt_runtime());
2400 }
2401}
2402
2403void sched_dl_do_global(void)
2404{
2405 u64 new_bw = -1;
2406 struct dl_bw *dl_b;
2407 int cpu;
2408 unsigned long flags;
2409
2410 def_dl_bandwidth.dl_period = global_rt_period();
2411 def_dl_bandwidth.dl_runtime = global_rt_runtime();
2412
2413 if (global_rt_runtime() != RUNTIME_INF)
2414 new_bw = to_ratio(global_rt_period(), global_rt_runtime());
2415
2416 /*
2417 * FIXME: As above...
2418 */
2419 for_each_possible_cpu(cpu) {
2420 rcu_read_lock_sched();
2421 dl_b = dl_bw_of(cpu);
2422
2423 raw_spin_lock_irqsave(&dl_b->lock, flags);
2424 dl_b->bw = new_bw;
2425 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
2426
2427 rcu_read_unlock_sched();
2428 init_dl_rq_bw_ratio(&cpu_rq(cpu)->dl);
2429 }
2430}
2431
2432/*
2433 * We must be sure that accepting a new task (or allowing changing the
2434 * parameters of an existing one) is consistent with the bandwidth
2435 * constraints. If yes, this function also accordingly updates the currently
2436 * allocated bandwidth to reflect the new situation.
2437 *
2438 * This function is called while holding p's rq->lock.
2439 */
2440int sched_dl_overflow(struct task_struct *p, int policy,
2441 const struct sched_attr *attr)
2442{
2443 struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
2444 u64 period = attr->sched_period ?: attr->sched_deadline;
2445 u64 runtime = attr->sched_runtime;
2446 u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
2447 int cpus, err = -1;
2448
2449 /* !deadline task may carry old deadline bandwidth */
2450 if (new_bw == p->dl.dl_bw && task_has_dl_policy(p))
2451 return 0;
2452
2453 /*
2454 * Either if a task, enters, leave, or stays -deadline but changes
2455 * its parameters, we may need to update accordingly the total
2456 * allocated bandwidth of the container.
2457 */
2458 raw_spin_lock(&dl_b->lock);
2459 cpus = dl_bw_cpus(task_cpu(p));
2460 if (dl_policy(policy) && !task_has_dl_policy(p) &&
2461 !__dl_overflow(dl_b, cpus, 0, new_bw)) {
2462 if (hrtimer_active(&p->dl.inactive_timer))
2463 __dl_clear(dl_b, p->dl.dl_bw, cpus);
2464 __dl_add(dl_b, new_bw, cpus);
2465 err = 0;
2466 } else if (dl_policy(policy) && task_has_dl_policy(p) &&
2467 !__dl_overflow(dl_b, cpus, p->dl.dl_bw, new_bw)) {
2468 /*
2469 * XXX this is slightly incorrect: when the task
2470 * utilization decreases, we should delay the total
2471 * utilization change until the task's 0-lag point.
2472 * But this would require to set the task's "inactive
2473 * timer" when the task is not inactive.
2474 */
2475 __dl_clear(dl_b, p->dl.dl_bw, cpus);
2476 __dl_add(dl_b, new_bw, cpus);
2477 dl_change_utilization(p, new_bw);
2478 err = 0;
2479 } else if (!dl_policy(policy) && task_has_dl_policy(p)) {
2480 /*
2481 * Do not decrease the total deadline utilization here,
2482 * switched_from_dl() will take care to do it at the correct
2483 * (0-lag) time.
2484 */
2485 err = 0;
2486 }
2487 raw_spin_unlock(&dl_b->lock);
2488
2489 return err;
2490}
2491
2492/*
2493 * This function initializes the sched_dl_entity of a newly becoming
2494 * SCHED_DEADLINE task.
2495 *
2496 * Only the static values are considered here, the actual runtime and the
2497 * absolute deadline will be properly calculated when the task is enqueued
2498 * for the first time with its new policy.
2499 */
2500void __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
2501{
2502 struct sched_dl_entity *dl_se = &p->dl;
2503
2504 dl_se->dl_runtime = attr->sched_runtime;
2505 dl_se->dl_deadline = attr->sched_deadline;
2506 dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline;
2507 dl_se->flags = attr->sched_flags;
2508 dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
2509 dl_se->dl_density = to_ratio(dl_se->dl_deadline, dl_se->dl_runtime);
2510}
2511
2512void __getparam_dl(struct task_struct *p, struct sched_attr *attr)
2513{
2514 struct sched_dl_entity *dl_se = &p->dl;
2515
2516 attr->sched_priority = p->rt_priority;
2517 attr->sched_runtime = dl_se->dl_runtime;
2518 attr->sched_deadline = dl_se->dl_deadline;
2519 attr->sched_period = dl_se->dl_period;
2520 attr->sched_flags = dl_se->flags;
2521}
2522
2523/*
2524 * This function validates the new parameters of a -deadline task.
2525 * We ask for the deadline not being zero, and greater or equal
2526 * than the runtime, as well as the period of being zero or
2527 * greater than deadline. Furthermore, we have to be sure that
2528 * user parameters are above the internal resolution of 1us (we
2529 * check sched_runtime only since it is always the smaller one) and
2530 * below 2^63 ns (we have to check both sched_deadline and
2531 * sched_period, as the latter can be zero).
2532 */
2533bool __checkparam_dl(const struct sched_attr *attr)
2534{
2535 /* deadline != 0 */
2536 if (attr->sched_deadline == 0)
2537 return false;
2538
2539 /*
2540 * Since we truncate DL_SCALE bits, make sure we're at least
2541 * that big.
2542 */
2543 if (attr->sched_runtime < (1ULL << DL_SCALE))
2544 return false;
2545
2546 /*
2547 * Since we use the MSB for wrap-around and sign issues, make
2548 * sure it's not set (mind that period can be equal to zero).
2549 */
2550 if (attr->sched_deadline & (1ULL << 63) ||
2551 attr->sched_period & (1ULL << 63))
2552 return false;
2553
2554 /* runtime <= deadline <= period (if period != 0) */
2555 if ((attr->sched_period != 0 &&
2556 attr->sched_period < attr->sched_deadline) ||
2557 attr->sched_deadline < attr->sched_runtime)
2558 return false;
2559
2560 return true;
2561}
2562
2563/*
2564 * This function clears the sched_dl_entity static params.
2565 */
2566void __dl_clear_params(struct task_struct *p)
2567{
2568 struct sched_dl_entity *dl_se = &p->dl;
2569
2570 dl_se->dl_runtime = 0;
2571 dl_se->dl_deadline = 0;
2572 dl_se->dl_period = 0;
2573 dl_se->flags = 0;
2574 dl_se->dl_bw = 0;
2575 dl_se->dl_density = 0;
2576
2577 dl_se->dl_throttled = 0;
2578 dl_se->dl_yielded = 0;
2579 dl_se->dl_non_contending = 0;
2580}
2581
2582bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
2583{
2584 struct sched_dl_entity *dl_se = &p->dl;
2585
2586 if (dl_se->dl_runtime != attr->sched_runtime ||
2587 dl_se->dl_deadline != attr->sched_deadline ||
2588 dl_se->dl_period != attr->sched_period ||
2589 dl_se->flags != attr->sched_flags)
2590 return true;
2591
2592 return false;
2593}
2594
2595#ifdef CONFIG_SMP
2596int dl_task_can_attach(struct task_struct *p, const struct cpumask *cs_cpus_allowed)
2597{
2598 unsigned int dest_cpu = cpumask_any_and(cpu_active_mask,
2599 cs_cpus_allowed);
2600 struct dl_bw *dl_b;
2601 bool overflow;
2602 int cpus, ret;
2603 unsigned long flags;
2604
2605 rcu_read_lock_sched();
2606 dl_b = dl_bw_of(dest_cpu);
2607 raw_spin_lock_irqsave(&dl_b->lock, flags);
2608 cpus = dl_bw_cpus(dest_cpu);
2609 overflow = __dl_overflow(dl_b, cpus, 0, p->dl.dl_bw);
2610 if (overflow)
2611 ret = -EBUSY;
2612 else {
2613 /*
2614 * We reserve space for this task in the destination
2615 * root_domain, as we can't fail after this point.
2616 * We will free resources in the source root_domain
2617 * later on (see set_cpus_allowed_dl()).
2618 */
2619 __dl_add(dl_b, p->dl.dl_bw, cpus);
2620 ret = 0;
2621 }
2622 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
2623 rcu_read_unlock_sched();
2624 return ret;
2625}
2626
2627int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur,
2628 const struct cpumask *trial)
2629{
2630 int ret = 1, trial_cpus;
2631 struct dl_bw *cur_dl_b;
2632 unsigned long flags;
2633
2634 rcu_read_lock_sched();
2635 cur_dl_b = dl_bw_of(cpumask_any(cur));
2636 trial_cpus = cpumask_weight(trial);
2637
2638 raw_spin_lock_irqsave(&cur_dl_b->lock, flags);
2639 if (cur_dl_b->bw != -1 &&
2640 cur_dl_b->bw * trial_cpus < cur_dl_b->total_bw)
2641 ret = 0;
2642 raw_spin_unlock_irqrestore(&cur_dl_b->lock, flags);
2643 rcu_read_unlock_sched();
2644 return ret;
2645}
2646
2647bool dl_cpu_busy(unsigned int cpu)
2648{
2649 unsigned long flags;
2650 struct dl_bw *dl_b;
2651 bool overflow;
2652 int cpus;
2653
2654 rcu_read_lock_sched();
2655 dl_b = dl_bw_of(cpu);
2656 raw_spin_lock_irqsave(&dl_b->lock, flags);
2657 cpus = dl_bw_cpus(cpu);
2658 overflow = __dl_overflow(dl_b, cpus, 0, 0);
2659 raw_spin_unlock_irqrestore(&dl_b->lock, flags);
2660 rcu_read_unlock_sched();
2661 return overflow;
2662}
2663#endif
2664
2321#ifdef CONFIG_SCHED_DEBUG 2665#ifdef CONFIG_SCHED_DEBUG
2322extern void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq); 2666extern void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq);
2323 2667
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e0329d10bdb8..d4eb3f67529d 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -218,9 +218,6 @@ static inline int dl_bandwidth_enabled(void)
218 return sysctl_sched_rt_runtime >= 0; 218 return sysctl_sched_rt_runtime >= 0;
219} 219}
220 220
221extern struct dl_bw *dl_bw_of(int i);
222extern int dl_bw_cpus(int i);
223
224struct dl_bw { 221struct dl_bw {
225 raw_spinlock_t lock; 222 raw_spinlock_t lock;
226 u64 bw, total_bw; 223 u64 bw, total_bw;
@@ -251,6 +248,20 @@ bool __dl_overflow(struct dl_bw *dl_b, int cpus, u64 old_bw, u64 new_bw)
251 248
252void dl_change_utilization(struct task_struct *p, u64 new_bw); 249void dl_change_utilization(struct task_struct *p, u64 new_bw);
253extern void init_dl_bw(struct dl_bw *dl_b); 250extern void init_dl_bw(struct dl_bw *dl_b);
251extern int sched_dl_global_validate(void);
252extern void sched_dl_do_global(void);
253extern int sched_dl_overflow(struct task_struct *p, int policy,
254 const struct sched_attr *attr);
255extern void __setparam_dl(struct task_struct *p, const struct sched_attr *attr);
256extern void __getparam_dl(struct task_struct *p, struct sched_attr *attr);
257extern bool __checkparam_dl(const struct sched_attr *attr);
258extern void __dl_clear_params(struct task_struct *p);
259extern bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr);
260extern int dl_task_can_attach(struct task_struct *p,
261 const struct cpumask *cs_cpus_allowed);
262extern int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur,
263 const struct cpumask *trial);
264extern bool dl_cpu_busy(unsigned int cpu);
254 265
255#ifdef CONFIG_CGROUP_SCHED 266#ifdef CONFIG_CGROUP_SCHED
256 267