Message ID | 20240226020939.45264-4-yaoma@linux.alibaba.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-80399-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:a81b:b0:108:e6aa:91d0 with SMTP id bq27csp1826794dyb; Sun, 25 Feb 2024 18:11:09 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCWIfHqAWfZixwiGEL7F3IcfN8bQ7/di8SsvZuvyBv/waO28DY+7asDfnDdxM6zwFxoGCrlwk1Rm/KqIsduJ+NWKioR+xQ== X-Google-Smtp-Source: AGHT+IEFvWEn3sw4zZlvTc3ZfXcwjTzxPwpuy3mh9Y3lPvQrGgn7u0iV/z2Ys1Mep2byvlYl0ftU X-Received: by 2002:a17:902:9a43:b0:1dc:4b04:13d4 with SMTP id x3-20020a1709029a4300b001dc4b0413d4mr4505581plv.8.1708913469093; Sun, 25 Feb 2024 18:11:09 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708913469; cv=pass; d=google.com; s=arc-20160816; b=v8Th3YVbQ/PoxcggQuUY+3DoW2uHDVLb7iK7LRo0ea2vWRn/l1Qml769IjbxpQHcQb RvimeOzQAF+zEiWb0Wzog37WLhrDpVit97/yzsLmV4VmD96OVrGzlZN1YYJZKoBTHPHz vUxad+wQKC2PUG485zOgAdwv7YcGoCMJh3z/eC5myyhOtl4ffDWdVB5ViIFYXqABmt55 DvD6NPNgpS0qdYM/0ikX5oZ5AQb5+SphEHdjghTLxmvbHFQbj4d0x4gdbTpakkdHf7yq hnnWC0F7V3Pp8dWHB3jF2fEAFuUyW9dGsNaC9jPJfh3bqXFM/3Fk1WGn0SzZd3Yb5OVG e4uw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=uN6ubd7T7BDgKGYOOcoXXMe2toDXWaMbHm9pDjI4o+Y=; fh=h1xXNY8doO7YpZZxFq7Tt2h1zNi8L7URk9NotQAeleE=; b=gKLNsmL6SLdjwamVP+Ep1z1RsYdX7vnrpRviAoaGmXilavvy12630zWXSGXn+QhfmG frJEs/6qAq1Z20h/lWxPZz20NozwlnjvDEIvKDlJAG9K6M+gElYUYAOShkz//rU+0y0a XXeuYM0gbQksrwjqUEfLpikmKkSYbT/iXqsMaprOSV3/ajLWy4VsuqJjMq8dEWEE44pK aZ+kq2vx64XrCYZqGRJRlCe1gSrfpJMvSJIU7XqRKmdHn3ct0SuKmKg+utPJEz/a878J AeTw7zh1UkPe8wy5NtlYRy3EcPZfsecwT2lljysDzVtvKrKC7WzU+BqUgQi0wG1fDBd8 R/oA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linux.alibaba.com header.s=default header.b=XIvyROOh; arc=pass (i=1 spf=pass spfdomain=linux.alibaba.com dkim=pass dkdomain=linux.alibaba.com dmarc=pass fromdomain=linux.alibaba.com); spf=pass (google.com: domain of linux-kernel+bounces-80399-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-80399-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.alibaba.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id p17-20020a170902e75100b001db339f4096si2937079plf.395.2024.02.25.18.11.09 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Feb 2024 18:11:09 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-80399-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.alibaba.com header.s=default header.b=XIvyROOh; arc=pass (i=1 spf=pass spfdomain=linux.alibaba.com dkim=pass dkdomain=linux.alibaba.com dmarc=pass fromdomain=linux.alibaba.com); spf=pass (google.com: domain of linux-kernel+bounces-80399-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-80399-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.alibaba.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id E30B82819EA for <ouuuleilei@gmail.com>; Mon, 26 Feb 2024 02:11:08 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 254781BDE6; Mon, 26 Feb 2024 02:10:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="XIvyROOh" Received: from out30-111.freemail.mail.aliyun.com (out30-111.freemail.mail.aliyun.com [115.124.30.111]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5AA9DF4D; Mon, 26 Feb 2024 02:10:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.111 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708913403; cv=none; b=X2nbQI38PArZ71ripedPzznD0yB8zKqsZ78/mu+TuwEpnG1l+cpqZG5dqfecRwLoGleSYOrkogNzR5i7ku6OpQUXynDCebQ+7EoO7wtZK/L9N+HDvBZxJJAfvV6tWvmuggqtSZJnvWUmXcKo4vUosSECmKzJDnc8skVMku9E+uU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708913403; c=relaxed/simple; bh=42gH4qBC/Oia0dXWguVUjy9QiaWAqbXw3cvqChcFo3U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=L3/H4/8XBN5YBktt/qgd9Oh/wf5d8wjrcgezEuJ3Pq2Hy3RMQzgfmv/bra4VYiJliX9YRWy0/fQAVl6Y+zGT76+RI/bBcaFuvj5oiaONxGTa+maLCOzb5SAelfRvU8CVvDEyfYtIr5EwsB0muI9adJGk+q8TPvUhSc32+R71RD8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=XIvyROOh; arc=none smtp.client-ip=115.124.30.111 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1708913393; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=uN6ubd7T7BDgKGYOOcoXXMe2toDXWaMbHm9pDjI4o+Y=; b=XIvyROOhSxK91wwUVMK+jpvHP1KDOSyC4gzrMSzUSJaH/hWd7ljCbUlZWGYFCopMWLHT40brMp8zNEkLDIljRz7PUiaRJ2LLHvpgOfotccsduQsc9aEbkWGuaYqHiAno3K4CknCjWsn4G4sk4E6jfi/JZCh5HIcakBIGpvCcD/U= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R131e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018046049;MF=yaoma@linux.alibaba.com;NM=1;PH=DS;RN=16;SR=0;TI=SMTPD_---0W1A1HdQ_1708913390; Received: from localhost.localdomain(mailfrom:yaoma@linux.alibaba.com fp:SMTPD_---0W1A1HdQ_1708913390) by smtp.aliyun-inc.com; Mon, 26 Feb 2024 10:09:52 +0800 From: Bitao Hu <yaoma@linux.alibaba.com> To: dianders@chromium.org, tglx@linutronix.de, liusong@linux.alibaba.com, akpm@linux-foundation.org, pmladek@suse.com, kernelfans@gmail.com, deller@gmx.de, npiggin@gmail.com, tsbogend@alpha.franken.de, James.Bottomley@HansenPartnership.com, jan.kiszka@siemens.com Cc: linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, yaoma@linux.alibaba.com Subject: [PATCHv10 3/4] genirq: Avoid summation loops for /proc/interrupts Date: Mon, 26 Feb 2024 10:09:38 +0800 Message-Id: <20240226020939.45264-4-yaoma@linux.alibaba.com> X-Mailer: git-send-email 2.37.1 (Apple Git-137.1) In-Reply-To: <20240226020939.45264-1-yaoma@linux.alibaba.com> References: <20240226020939.45264-1-yaoma@linux.alibaba.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791925649621612994 X-GMAIL-MSGID: 1791925649621612994 |
Series |
*** Detect interrupt storm in softlockup ***
|
|
Commit Message
Bitao Hu
Feb. 26, 2024, 2:09 a.m. UTC
We could use the irq_desc::tot_count member to avoid the summation
loop for interrupts which are not marked as 'PER_CPU' interrupts in
'show_interrupts'. This could reduce the time overhead of reading
/proc/interrupts.
Originally-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Bitao Hu <yaoma@linux.alibaba.com>
---
include/linux/irqdesc.h | 2 ++
kernel/irq/irqdesc.c | 2 +-
kernel/irq/proc.c | 9 +++++++--
3 files changed, 10 insertions(+), 3 deletions(-)
Comments
在 2024/2/26 10:09, Bitao Hu 写道: > We could use the irq_desc::tot_count member to avoid the summation > loop for interrupts which are not marked as 'PER_CPU' interrupts in > 'show_interrupts'. This could reduce the time overhead of reading > /proc/interrupts. > > Originally-by: Thomas Gleixner <tglx@linutronix.de> > Signed-off-by: Bitao Hu <yaoma@linux.alibaba.com> > --- > include/linux/irqdesc.h | 2 ++ > kernel/irq/irqdesc.c | 2 +- > kernel/irq/proc.c | 9 +++++++-- > 3 files changed, 10 insertions(+), 3 deletions(-) > > diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h > index 2912b1998670..1ee96d7232b4 100644 > --- a/include/linux/irqdesc.h > +++ b/include/linux/irqdesc.h > @@ -121,6 +121,8 @@ static inline void irq_unlock_sparse(void) { } > extern struct irq_desc irq_desc[NR_IRQS]; > #endif > > +extern bool irq_is_nmi(struct irq_desc *desc); > + > static inline unsigned int irq_desc_kstat_cpu(struct irq_desc *desc, > unsigned int cpu) > { > diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c > index 9cd17080b2d8..56a767957a9d 100644 > --- a/kernel/irq/irqdesc.c > +++ b/kernel/irq/irqdesc.c > @@ -955,7 +955,7 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) > return desc && desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0; > } > > -static bool irq_is_nmi(struct irq_desc *desc) > +bool irq_is_nmi(struct irq_desc *desc) > { > return desc->istate & IRQS_NMI; > } > diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c > index 6954e0a02047..b3b1b93f0410 100644 > --- a/kernel/irq/proc.c > +++ b/kernel/irq/proc.c > @@ -489,8 +489,13 @@ int show_interrupts(struct seq_file *p, void *v) > goto outsparse; > > if (desc->kstat_irqs) { > - for_each_online_cpu(j) > - any_count |= data_race(per_cpu(desc->kstat_irqs->cnt, j)); > + if (!irq_settings_is_per_cpu_devid(desc) && > + !irq_settings_is_per_cpu(desc) && > + !irq_is_nmi(desc)) > + any_count = data_race(desc->tot_count); > + else > + for_each_online_cpu(j) > + any_count |= data_race(per_cpu(desc->kstat_irqs->cnt, j)); > } > > if ((!desc->action || irq_desc_is_chained(desc)) && !any_count) The modification borrows from the implementation of |kstat_irqs. Looks good.| |Reviewed-by: Liu Song <liusong@linux.alibaba.com> | ||
On Mon, Feb 26 2024 at 10:09, Bitao Hu wrote: > We could use the irq_desc::tot_count member to avoid the summation > loop for interrupts which are not marked as 'PER_CPU' interrupts in > 'show_interrupts'. This could reduce the time overhead of reading > /proc/interrupts. "Could" is not really a technical term. Either we do or we do not. Also please provide context for your change and avoid the 'We'. > --- a/include/linux/irqdesc.h > +++ b/include/linux/irqdesc.h > @@ -121,6 +121,8 @@ static inline void irq_unlock_sparse(void) { } > extern struct irq_desc irq_desc[NR_IRQS]; > #endif > > +extern bool irq_is_nmi(struct irq_desc *desc); > + If at all this wants to be in kernel/irq/internal.h. There is zero reason to expose this globally. > -static bool irq_is_nmi(struct irq_desc *desc) > +bool irq_is_nmi(struct irq_desc *desc) > { > return desc->istate & IRQS_NMI; > } If at all this really wants to be a static inline in internals.h, but instead of blindly copying code this can be done smarter: unsigned int kstat_irq_desc(struct irq_desc *desc) { unsigned int sum = 0; int cpu; if (!irq_settings_is_per_cpu_devid(desc) && !irq_settings_is_per_cpu(desc) && !irq_is_nmi(desc)) return data_race(desc->tot_count); for_each_possible_cpu(cpu) sum += data_race(*per_cpu_ptr(desc->kstat_irqs, cpu)); return sum; } and then let kstat_irqs() and show_interrupts() use it. See? With that a proper changelog would be: show_interrupts() unconditionally accumulates the per CPU interrupt statistics to determine whether an interrupt was ever raised. This can be avoided for all interrupts which are not strictly per CPU and not of type NMI because those interrupts provide already an accumulated counter. The required logic is already implemented in kstat_irqs(). Split the inner access logic out of kstat_irqs() and use it for kstat_irqs() and show_interrupts() to avoid the accumulation loop when possible. Thanks, tglx
Hi, On 2024/2/27 17:26, Thomas Gleixner wrote: > On Mon, Feb 26 2024 at 10:09, Bitao Hu wrote: >> We could use the irq_desc::tot_count member to avoid the summation >> loop for interrupts which are not marked as 'PER_CPU' interrupts in >> 'show_interrupts'. This could reduce the time overhead of reading >> /proc/interrupts. > > "Could" is not really a technical term. Either we do or we do not. Also > please provide context for your change and avoid the 'We'. OK. > >> --- a/include/linux/irqdesc.h >> +++ b/include/linux/irqdesc.h >> @@ -121,6 +121,8 @@ static inline void irq_unlock_sparse(void) { } >> extern struct irq_desc irq_desc[NR_IRQS]; >> #endif >> >> +extern bool irq_is_nmi(struct irq_desc *desc); >> + > > If at all this wants to be in kernel/irq/internal.h. There is zero > reason to expose this globally. > >> -static bool irq_is_nmi(struct irq_desc *desc) >> +bool irq_is_nmi(struct irq_desc *desc) >> { >> return desc->istate & IRQS_NMI; >> } > > If at all this really wants to be a static inline in internals.h, but > instead of blindly copying code this can be done smarter: > > unsigned int kstat_irq_desc(struct irq_desc *desc) > { > unsigned int sum = 0; > int cpu; > > if (!irq_settings_is_per_cpu_devid(desc) && > !irq_settings_is_per_cpu(desc) && > !irq_is_nmi(desc)) > return data_race(desc->tot_count); > > for_each_possible_cpu(cpu) > sum += data_race(*per_cpu_ptr(desc->kstat_irqs, cpu)); > return sum; > } > > and then let kstat_irqs() and show_interrupts() use it. See? I have a concern. kstat_irqs() uses for_each_possible_cpu() for summation. However, show_interrupts() uses for_each_online_cpu(), which means it only outputs interrupt statistics for online cpus. If we use for_each_possible_cpu() in show_interrupts() to calculate 'any_count', there could be a problem with the following scenario: If an interrupt has a count of zero on online cpus but a non-zero count on possible cpus, then 'any_count' would not be zero, and the statistics for that interrupt would be output, which is not the desired behavior for show_interrupts(). Therefore, I think it's not good to have kstat_irqs() and show_interrupts() both use the same logic. What do you think? > > With that a proper changelog would be: > > show_interrupts() unconditionally accumulates the per CPU interrupt > statistics to determine whether an interrupt was ever raised. > > This can be avoided for all interrupts which are not strictly per CPU > and not of type NMI because those interrupts provide already an > accumulated counter. The required logic is already implemented in > kstat_irqs(). > > Split the inner access logic out of kstat_irqs() and use it for > kstat_irqs() and show_interrupts() to avoid the accumulation loop > when possible. > Best Regards, Bitao Hu
On Tue, Feb 27 2024 at 19:20, Bitao Hu wrote: > On 2024/2/27 17:26, Thomas Gleixner wrote: >> >> and then let kstat_irqs() and show_interrupts() use it. See? > > I have a concern. kstat_irqs() uses for_each_possible_cpu() for > summation. However, show_interrupts() uses for_each_online_cpu(), > which means it only outputs interrupt statistics for online cpus. > If we use for_each_possible_cpu() in show_interrupts() to calculate > 'any_count', there could be a problem with the following scenario: > If an interrupt has a count of zero on online cpus but a non-zero > count on possible cpus, then 'any_count' would not be zero, and the > statistics for that interrupt would be output, which is not the > desired behavior for show_interrupts(). Therefore, I think it's not > good to have kstat_irqs() and show_interrupts() both use the same > logic. What do you think? Good point. But you simply can have unsigned int kstat_irq_desc(struct irq_desc *desc, const struct cpumask *mask) and hand in the appropriate cpumask, which still shares the code, no? Thanks, tglx
On 2024/2/27 23:39, Thomas Gleixner wrote: > On Tue, Feb 27 2024 at 19:20, Bitao Hu wrote: >> On 2024/2/27 17:26, Thomas Gleixner wrote: >>> >>> and then let kstat_irqs() and show_interrupts() use it. See? >> >> I have a concern. kstat_irqs() uses for_each_possible_cpu() for >> summation. However, show_interrupts() uses for_each_online_cpu(), >> which means it only outputs interrupt statistics for online cpus. >> If we use for_each_possible_cpu() in show_interrupts() to calculate >> 'any_count', there could be a problem with the following scenario: >> If an interrupt has a count of zero on online cpus but a non-zero >> count on possible cpus, then 'any_count' would not be zero, and the >> statistics for that interrupt would be output, which is not the >> desired behavior for show_interrupts(). Therefore, I think it's not >> good to have kstat_irqs() and show_interrupts() both use the same >> logic. What do you think? > > Good point. But you simply can have > > unsigned int kstat_irq_desc(struct irq_desc *desc, const struct cpumask *mask) > > and hand in the appropriate cpumask, which still shares the code, no? > Alright, that is a good approach.
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 2912b1998670..1ee96d7232b4 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -121,6 +121,8 @@ static inline void irq_unlock_sparse(void) { } extern struct irq_desc irq_desc[NR_IRQS]; #endif +extern bool irq_is_nmi(struct irq_desc *desc); + static inline unsigned int irq_desc_kstat_cpu(struct irq_desc *desc, unsigned int cpu) { diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 9cd17080b2d8..56a767957a9d 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -955,7 +955,7 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) return desc && desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0; } -static bool irq_is_nmi(struct irq_desc *desc) +bool irq_is_nmi(struct irq_desc *desc) { return desc->istate & IRQS_NMI; } diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 6954e0a02047..b3b1b93f0410 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -489,8 +489,13 @@ int show_interrupts(struct seq_file *p, void *v) goto outsparse; if (desc->kstat_irqs) { - for_each_online_cpu(j) - any_count |= data_race(per_cpu(desc->kstat_irqs->cnt, j)); + if (!irq_settings_is_per_cpu_devid(desc) && + !irq_settings_is_per_cpu(desc) && + !irq_is_nmi(desc)) + any_count = data_race(desc->tot_count); + else + for_each_online_cpu(j) + any_count |= data_race(per_cpu(desc->kstat_irqs->cnt, j)); } if ((!desc->action || irq_desc_is_chained(desc)) && !any_count)