From patchwork Tue Mar 27 21:58:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 10311775 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F352D6037D for ; Tue, 27 Mar 2018 21:58:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DAAC628E0C for ; Tue, 27 Mar 2018 21:58:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF3A329063; Tue, 27 Mar 2018 21:58:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6362D28E0C for ; Tue, 27 Mar 2018 21:58:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752190AbeC0V61 (ORCPT ); Tue, 27 Mar 2018 17:58:27 -0400 Received: from cloudserver094114.home.pl ([79.96.170.134]:65513 "EHLO cloudserver094114.home.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751901AbeC0V60 (ORCPT ); Tue, 27 Mar 2018 17:58:26 -0400 Received: from 79.184.254.228.ipv4.supernova.orange.pl (79.184.254.228) (HELO aspire.rjw.lan) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83) id 951b0f6c5eef7b26; Tue, 27 Mar 2018 23:58:24 +0200 From: "Rafael J. Wysocki" To: Linux PM Cc: Peter Zijlstra , Frederic Weisbecker , Thomas Gleixner , Paul McKenney , Thomas Ilsche , Doug Smythies , Rik van Riel , Aubrey Li , Mike Galbraith , LKML Subject: [PATCH] cpuidle: poll_state: Avoid invoking local_clock() too often Date: Tue, 27 Mar 2018 23:58:45 +0200 Message-ID: <2095821.OCbkRpinqI@aspire.rjw.lan> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rafael J. Wysocki Rik reports that he sees an increase in CPU use in one benchmark due to commit 612f1a22f067 "cpuidle: poll_state: Add time limit to poll_idle()" that caused poll_idle() to call local_clock() in every iteration of the loop. Utilization increase generally means more non-idle time with respect to total CPU time (on the average) which implies reduced CPU frequency. Doug reports that limiting the rate of local_clock() invocations in there causes much less power to be drawn during a CPU-intensive parallel workload (with idle states 1 and 2 disabled to enforce more state 0 residency). These two reports together suggest that executing local_clock() on multiple CPUs in parallel at a high rate may cause chips to get hot and trigger thermal/power limits on them to kick in, so reduce the rate of local_clock() invocations in poll_idle() to avoid that issue. Fixes: 612f1a22f067 "cpuidle: poll_state: Add time limit to poll_idle()" Reported-by: Rik van Riel Reported-by: Doug Smythies Signed-off-by: Rafael J. Wysocki Tested-by: Rik van Riel Reviewed-by: Rik van Riel --- I've settled for POLL_IDLE_RELAX_COUNT = 200 after quite a bit of back-and-forth and a number of test runs. It may need to be refined going forward if somebody has a problem with the current one. --- drivers/cpuidle/poll_state.c | 6 ++++++ 1 file changed, 6 insertions(+) Index: linux-pm/drivers/cpuidle/poll_state.c =================================================================== --- linux-pm.orig/drivers/cpuidle/poll_state.c +++ linux-pm/drivers/cpuidle/poll_state.c @@ -10,6 +10,7 @@ #include #define POLL_IDLE_TIME_LIMIT (TICK_NSEC / 16) +#define POLL_IDLE_RELAX_COUNT 200 static int __cpuidle poll_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -18,9 +19,14 @@ static int __cpuidle poll_idle(struct cp local_irq_enable(); if (!current_set_polling_and_test()) { + unsigned int loop_count = 0; + while (!need_resched()) { cpu_relax(); + if (loop_count++ < POLL_IDLE_RELAX_COUNT) + continue; + loop_count = 0; if (local_clock() - time_start > POLL_IDLE_TIME_LIMIT) break; }