Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752628AbbDCMlp (ORCPT ); Fri, 3 Apr 2015 08:41:45 -0400 Received: from forward-corp1f.mail.yandex.net ([95.108.130.40]:35875 "EHLO forward-corp1f.mail.yandex.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751435AbbDCMln (ORCPT ); Fri, 3 Apr 2015 08:41:43 -0400 Authentication-Results: smtpcorp1m.mail.yandex.net; dkim=pass header.i=@yandex-team.ru Subject: [PATCH RFC] sched/fair: fix sudden expiration of cfq quota in put_prev_task() From: Konstantin Khlebnikov To: Peter Zijlstra , Ingo Molnar , linux-kernel@vger.kernel.org Cc: Ben Segall , Roman Gushchin Date: Fri, 03 Apr 2015 15:41:38 +0300 Message-ID: <20150403124138.1349.11633.stgit@buzz> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2479 Lines: 66 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 --- 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/