From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754435AbdLDNtx (ORCPT ); Mon, 4 Dec 2017 08:49:53 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:42210 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754426AbdLDNtr (ORCPT ); Mon, 4 Dec 2017 08:49:47 -0500 X-Google-Smtp-Source: AGs4zMbetHucoAQcJbfsfONbibo5S5bQ2D0UQAB0wSwdK/myDOuwU4luw1x0vuRgUwtLNfTi0+3RWQ== From: Sergey Senozhatsky To: Steven Rostedt , Petr Mladek Cc: Jan Kara , Andrew Morton , Peter Zijlstra , Rafael Wysocki , Pavel Machek , Tetsuo Handa , Tejun Heo , linux-kernel@vger.kernel.org, Sergey Senozhatsky , Sergey Senozhatsky Subject: [RFC][PATCHv6 10/12] printk: move offloading logic to per-cpu Date: Mon, 4 Dec 2017 22:48:23 +0900 Message-Id: <20171204134825.7822-11-sergey.senozhatsky@gmail.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171204134825.7822-1-sergey.senozhatsky@gmail.com> References: <20171204134825.7822-1-sergey.senozhatsky@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We have a global offloading state and make the offloading decision based on printing task pointer and elapsed time. If we keep seeing the same task performing printing for too long we request offloading; otherwise, when we see that printing is now performed by another task, we reset the printing task pointer and its elapsed counter. This, however, will not work in the following case: =============================================================================== CPU0 CPU1 //taskA //taskB preempt_disable() preempt_disable() printk() console_trylock() console_unlock() printing_task = taskA up() printk() console_trylock() console_unlock() printing_task = taskB ^^^ reset offloading control up() printk() console_trylock() console_unlock() printing_task = taskA ^^^ reset offloading control up() printk() console_trylock() console_unlock() printing_task = taskB ^^^ reset offloading control up() ... =============================================================================== So this printk ping-pong confuses our offloading control logic. Move it to per-CPU area and have a separate offloading control on every CPU. Signed-off-by: Sergey Senozhatsky --- kernel/printk/printk.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2a12d4c02da1..2f9697c71cf1 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -560,12 +560,12 @@ static inline int offloading_threshold(void) * amount of time a process can print from console_unlock(). * * This function must be called from 'printk_safe' context under - * console_sem lock. + * console_sem lock with preemption disabled. */ static inline bool should_handoff_printing(u64 printing_start_ts) { + static DEFINE_PER_CPU(u64, printing_elapsed); static struct task_struct *printing_task; - static u64 printing_elapsed; u64 now = local_clock(); bool emergency = !printk_offloading_enabled(); @@ -578,19 +578,26 @@ static inline bool should_handoff_printing(u64 printing_start_ts) /* A new task - reset the counters. */ if (printing_task != current) { + __this_cpu_write(printing_elapsed, 0); printing_task = current; - printing_elapsed = 0; return false; } - if (time_after_eq64(now, printing_start_ts)) - printing_elapsed += now - printing_start_ts; + if (time_after_eq64(now, printing_start_ts)) { + u64 t = __this_cpu_read(printing_elapsed); + + t += now - printing_start_ts; + __this_cpu_write(printing_elapsed, t); + } /* Shrink down to seconds and check the offloading threshold */ - if ((printing_elapsed >> 30LL) < offloading_threshold()) + if ((__this_cpu_read(printing_elapsed) >> 30LL) < + offloading_threshold()) return false; if (current == printk_kthread) { + unsigned int cpu; + /* * All tasks must offload - we don't want to keep console_sem * locked for too long. However, printk_kthread may be the @@ -603,7 +610,8 @@ static inline bool should_handoff_printing(u64 printing_start_ts) * console_unlock(), it will have another full * `offloading_threshold()' time slice. */ - printing_elapsed = 0; + for_each_possible_cpu(cpu) + per_cpu(printing_elapsed, cpu) = 0; return true; } -- 2.15.1