Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757222AbdDQU4k (ORCPT ); Mon, 17 Apr 2017 16:56:40 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:28109 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757168AbdDQU4i (ORCPT ); Mon, 17 Apr 2017 16:56:38 -0400 To: LKML , Ingo Molnar , Peter Zijlstra From: Dave Kleikamp Subject: [PATCH] sched/rt: minimize rq->lock contention in do_sched_rt_period_timer() Message-ID: <22884186-a92c-9475-7b4a-118a31a5b647@oracle.com> Date: Mon, 17 Apr 2017 15:56:04 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1333 Lines: 41 With CONFIG_RT_GROUP_SCHED defined, do_sched_rt_period_timer() sequentially takes each cpu's rq->lock. On a large, busy system, the cumulative time it takes to acquire each lock can be excessive, even triggering a watchdog timeout. If rt_rq_rt_time and rt_rq->rt_nr_running are both zero, this function does nothing while holding the lock, so don't bother taking it at all. Orabug: 25491970 Signed-off-by: Dave Kleikamp Cc: Ingo Molnar Cc: Peter Zijlstra --- kernel/sched/rt.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 9f3e40226dec..ae4a8c529a02 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -840,6 +840,17 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) int enqueue = 0; struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i); struct rq *rq = rq_of_rt_rq(rt_rq); + int skip; + + /* + * When span == cpu_online_mask, taking each rq->lock + * can be time-consuming. Try to avoid it when possible. + */ + raw_spin_lock(&rt_rq->rt_runtime_lock); + skip = !rt_rq->rt_time && !rt_rq->rt_nr_running; + raw_spin_unlock(&rt_rq->rt_runtime_lock); + if (skip) + continue; raw_spin_lock(&rq->lock); if (rt_rq->rt_time) { -- 2.12.2