[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150403124138.1349.11633.stgit@buzz>
Date: Fri, 03 Apr 2015 15:41:38 +0300
From: Konstantin Khlebnikov <khlebnikov@...dex-team.ru>
To: Peter Zijlstra <peterz@...radead.org>,
Ingo Molnar <mingo@...hat.com>, linux-kernel@...r.kernel.org
Cc: Ben Segall <bsegall@...gle.com>,
Roman Gushchin <klamm@...dex-team.ru>
Subject: [PATCH RFC] sched/fair: fix sudden expiration of cfq quota in
put_prev_task()
Pick_next_task_fair() must be sure that here is at least one runnable
task before calling put_prev_task(), but put_prev_task() can expire
last remains of cfs quota and throttle all currently runnable tasks.
As a result pick_next_task_fair() cannot find next task and crashes.
This patch leaves 1 in ->runtime_remaining when current assignation
expires and tries to refill it right after that. In the worst case
task will be scheduled once and throttled at the end of slice.
Signed-off-by: Konstantin Khlebnikov <khlebnikov@...dex-team.ru>
---
kernel/sched/fair.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7ce18f3c097a..91785d077db4 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3447,11 +3447,12 @@ static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
{
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
- /* if the deadline is ahead of our clock, nothing to do */
- if (likely((s64)(rq_clock(rq_of(cfs_rq)) - cfs_rq->runtime_expires) < 0))
+ /* nothing to expire */
+ if (cfs_rq->runtime_remaining <= 0)
return;
- if (cfs_rq->runtime_remaining < 0)
+ /* if the deadline is ahead of our clock, nothing to do */
+ if (likely((s64)(rq_clock(rq_of(cfs_rq)) - cfs_rq->runtime_expires) < 0))
return;
/*
@@ -3469,8 +3470,14 @@ static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
/* extend local deadline, drift is bounded above by 2 ticks */
cfs_rq->runtime_expires += TICK_NSEC;
} else {
- /* global deadline is ahead, expiration has passed */
- cfs_rq->runtime_remaining = 0;
+ /*
+ * Global deadline is ahead, expiration has passed.
+ *
+ * Do not expire runtime completely. Otherwise put_prev_task()
+ * can throttle all tasks when we already checked nr_running or
+ * put_prev_entity() can throttle already chosen next entity.
+ */
+ cfs_rq->runtime_remaining = 1;
}
}
@@ -3480,7 +3487,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
cfs_rq->runtime_remaining -= delta_exec;
expire_cfs_rq_runtime(cfs_rq);
- if (likely(cfs_rq->runtime_remaining > 0))
+ if (likely(cfs_rq->runtime_remaining > 1))
return;
/*
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists