aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-04-20 12:53:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-04-20 12:53:36 -0400
commit2b4cf5850db6acef2bbef52e3011f9bf93484209 (patch)
tree9dd1b0df3e1c5aeef16e65a99c97008349e73855
parentde3af9a99013fdb0358bb990e9bed0172c65bba9 (diff)
parent1b02cd6a2d7f3e2a6a5262887d2cb2912083e42f (diff)
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fixes from Ingo Molnar: "A deadline scheduler warning/race fix, and a cfs_period_us quota calculation workaround where the real fix looks too involved to merge immediately" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/deadline: Correctly handle active 0-lag timers sched/fair: Limit sched_cfs_period_timer() loop to avoid hard lockup
-rw-r--r--kernel/sched/deadline.c3
-rw-r--r--kernel/sched/fair.c25
2 files changed, 26 insertions, 2 deletions
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 6a73e41a2016..43901fa3f269 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -252,7 +252,6 @@ static void task_non_contending(struct task_struct *p)
252 if (dl_entity_is_special(dl_se)) 252 if (dl_entity_is_special(dl_se))
253 return; 253 return;
254 254
255 WARN_ON(hrtimer_active(&dl_se->inactive_timer));
256 WARN_ON(dl_se->dl_non_contending); 255 WARN_ON(dl_se->dl_non_contending);
257 256
258 zerolag_time = dl_se->deadline - 257 zerolag_time = dl_se->deadline -
@@ -269,7 +268,7 @@ static void task_non_contending(struct task_struct *p)
269 * If the "0-lag time" already passed, decrease the active 268 * If the "0-lag time" already passed, decrease the active
270 * utilization now, instead of starting a timer 269 * utilization now, instead of starting a timer
271 */ 270 */
272 if (zerolag_time < 0) { 271 if ((zerolag_time < 0) || hrtimer_active(&dl_se->inactive_timer)) {
273 if (dl_task(p)) 272 if (dl_task(p))
274 sub_running_bw(dl_se, dl_rq); 273 sub_running_bw(dl_se, dl_rq);
275 if (!dl_task(p) || p->state == TASK_DEAD) { 274 if (!dl_task(p) || p->state == TASK_DEAD) {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 40bd1e27b1b7..a4d9e14bf138 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4885,6 +4885,8 @@ static enum hrtimer_restart sched_cfs_slack_timer(struct hrtimer *timer)
4885 return HRTIMER_NORESTART; 4885 return HRTIMER_NORESTART;
4886} 4886}
4887 4887
4888extern const u64 max_cfs_quota_period;
4889
4888static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer) 4890static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
4889{ 4891{
4890 struct cfs_bandwidth *cfs_b = 4892 struct cfs_bandwidth *cfs_b =
@@ -4892,6 +4894,7 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
4892 unsigned long flags; 4894 unsigned long flags;
4893 int overrun; 4895 int overrun;
4894 int idle = 0; 4896 int idle = 0;
4897 int count = 0;
4895 4898
4896 raw_spin_lock_irqsave(&cfs_b->lock, flags); 4899 raw_spin_lock_irqsave(&cfs_b->lock, flags);
4897 for (;;) { 4900 for (;;) {
@@ -4899,6 +4902,28 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
4899 if (!overrun) 4902 if (!overrun)
4900 break; 4903 break;
4901 4904
4905 if (++count > 3) {
4906 u64 new, old = ktime_to_ns(cfs_b->period);
4907
4908 new = (old * 147) / 128; /* ~115% */
4909 new = min(new, max_cfs_quota_period);
4910
4911 cfs_b->period = ns_to_ktime(new);
4912
4913 /* since max is 1s, this is limited to 1e9^2, which fits in u64 */
4914 cfs_b->quota *= new;
4915 cfs_b->quota = div64_u64(cfs_b->quota, old);
4916
4917 pr_warn_ratelimited(
4918 "cfs_period_timer[cpu%d]: period too short, scaling up (new cfs_period_us %lld, cfs_quota_us = %lld)\n",
4919 smp_processor_id(),
4920 div_u64(new, NSEC_PER_USEC),
4921 div_u64(cfs_b->quota, NSEC_PER_USEC));
4922
4923 /* reset count so we don't come right back in here */
4924 count = 0;
4925 }
4926
4902 idle = do_sched_cfs_period_timer(cfs_b, overrun, flags); 4927 idle = do_sched_cfs_period_timer(cfs_b, overrun, flags);
4903 } 4928 }
4904 if (idle) 4929 if (idle)