From nobody Sun May 10 07:14:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 948E1482F2 for ; Fri, 27 Dec 2024 19:36:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735328172; cv=none; b=Eh3qs4j6TBxEgwiG7os6Vc20xC7o0nNCDegn28AuApYkzICoHNGVm+fKofSZ/DZUNmNvojn0aRjDky+j+T01c0CdTB935yLBles5IHXKM+SAbwr44IcoMTCLck+HuOldgq4QN+WpiIGGrhKFBFRd8Ja6odReNLCVGoXAQvAQ1sw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735328172; c=relaxed/simple; bh=gi1mgObFZnngxiRdyLDG/0D1WfCMAQOijWFoHRuCv0M=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type; b=N0HWHtCd5X+QHjgKFz7bJ5yg+1XIWxnkVDsaXon3WLHA2IXVK8JgBBGt19WECGby7jC58O3KbPUM0bOhK0+XGomQ23YBUAeFrKXNlJHonbeW95CrEv/OrxV4IyDc05TLyuUkJW4TOOahOI6b5QXm30ucHSOnEErgxSwE/6VObl4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C0DFFC4CED0; Fri, 27 Dec 2024 19:36:11 +0000 (UTC) Date: Fri, 27 Dec 2024 14:37:12 -0500 From: Steven Rostedt To: Linus Torvalds Cc: LKML , Tomas Glozar Subject: [GIT PULL] trace/tooling: Fix rtla/timerlat histogram for zero size samples Message-ID: <20241227143712.60052a70@gandalf.local.home> X-Mailer: Claws Mail 3.20.0git84 (GTK+ 2.24.33; x86_64-pc-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Linus, tooling fixes for v6.13: - Fix rtla divide by zero when the count is zero in histograms Please pull the latest trace-tools-v6.13-rc4 tree, which can be found at: git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git trace-tools-v6.13-rc4 Tag SHA1: d5ed5f2ba442d5948caaf5d6629c477bb13f7585 Head SHA1: 6cc45f8c1f898570916044f606be9890d295e129 Tomas Glozar (1): rtla/timerlat: Fix histogram ALL for zero samples ---- tools/tracing/rtla/src/timerlat_hist.c | 177 ++++++++++++++++++-----------= ---- 1 file changed, 96 insertions(+), 81 deletions(-) --------------------------- commit 6cc45f8c1f898570916044f606be9890d295e129 Author: Tomas Glozar Date: Wed Nov 27 14:41:30 2024 +0100 rtla/timerlat: Fix histogram ALL for zero samples =20 rtla timerlat hist currently computers the minimum, maximum and average latency even in cases when there are zero samples. This leads to nonsensical values being calculated for maximum and minimum, and to divide by zero for average. =20 A similar bug is fixed by 01b05fc0e5f3 ("rtla/timerlat: Fix histogram report when a cpu count is 0") but the bug still remains for printing the sum over all CPUs in timerlat_print_stats_all. =20 The issue can be reproduced with this command: =20 $ rtla timerlat hist -U -d 1s Index over: count: min: avg: max: Floating point exception (core dumped) =20 (There are always no samples with -U unless the user workload is created.) =20 Fix the bug by omitting max/min/avg when sample count is zero, displaying a dash instead, just like we already do for the individual CPUs. The logic is moved into a new function called format_summary_value, which is used for both the individual CPUs and for the overall summary. =20 Cc: stable@vger.kernel.org Link: https://lore.kernel.org/20241127134130.51171-1-tglozar@redhat.com Fixes: 1462501c7a8 ("rtla/timerlat: Add a summary for hist mode") Signed-off-by: Tomas Glozar Signed-off-by: Steven Rostedt (Google) diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/sr= c/timerlat_hist.c index 8b66387e5f35..4403cc4eba30 100644 --- a/tools/tracing/rtla/src/timerlat_hist.c +++ b/tools/tracing/rtla/src/timerlat_hist.c @@ -281,6 +281,21 @@ static void timerlat_hist_header(struct osnoise_tool *= tool) trace_seq_reset(s); } =20 +/* + * format_summary_value - format a line of summary value (min, max or avg) + * of hist data + */ +static void format_summary_value(struct trace_seq *seq, + int count, + unsigned long long val, + bool avg) +{ + if (count) + trace_seq_printf(seq, "%9llu ", avg ? val / count : val); + else + trace_seq_printf(seq, "%9c ", '-'); +} + /* * timerlat_print_summary - print the summary of the hist data to the outp= ut */ @@ -328,29 +343,23 @@ timerlat_print_summary(struct timerlat_hist_params *p= arams, if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count) continue; =20 - if (!params->no_irq) { - if (data->hist[cpu].irq_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].min_irq); - else - trace_seq_printf(trace->seq, " - "); - } + if (!params->no_irq) + format_summary_value(trace->seq, + data->hist[cpu].irq_count, + data->hist[cpu].min_irq, + false); =20 - if (!params->no_thread) { - if (data->hist[cpu].thread_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].min_thread); - else - trace_seq_printf(trace->seq, " - "); - } + if (!params->no_thread) + format_summary_value(trace->seq, + data->hist[cpu].thread_count, + data->hist[cpu].min_thread, + false); =20 - if (params->user_hist) { - if (data->hist[cpu].user_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].min_user); - else - trace_seq_printf(trace->seq, " - "); - } + if (params->user_hist) + format_summary_value(trace->seq, + data->hist[cpu].user_count, + data->hist[cpu].min_user, + false); } trace_seq_printf(trace->seq, "\n"); =20 @@ -364,29 +373,23 @@ timerlat_print_summary(struct timerlat_hist_params *p= arams, if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count) continue; =20 - if (!params->no_irq) { - if (data->hist[cpu].irq_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].sum_irq / data->hist[cpu].irq_count); - else - trace_seq_printf(trace->seq, " - "); - } + if (!params->no_irq) + format_summary_value(trace->seq, + data->hist[cpu].irq_count, + data->hist[cpu].sum_irq, + true); =20 - if (!params->no_thread) { - if (data->hist[cpu].thread_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].sum_thread / data->hist[cpu].thread_count); - else - trace_seq_printf(trace->seq, " - "); - } + if (!params->no_thread) + format_summary_value(trace->seq, + data->hist[cpu].thread_count, + data->hist[cpu].sum_thread, + true); =20 - if (params->user_hist) { - if (data->hist[cpu].user_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].sum_user / data->hist[cpu].user_count); - else - trace_seq_printf(trace->seq, " - "); - } + if (params->user_hist) + format_summary_value(trace->seq, + data->hist[cpu].user_count, + data->hist[cpu].sum_user, + true); } trace_seq_printf(trace->seq, "\n"); =20 @@ -400,29 +403,23 @@ timerlat_print_summary(struct timerlat_hist_params *p= arams, if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count) continue; =20 - if (!params->no_irq) { - if (data->hist[cpu].irq_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].max_irq); - else - trace_seq_printf(trace->seq, " - "); - } + if (!params->no_irq) + format_summary_value(trace->seq, + data->hist[cpu].irq_count, + data->hist[cpu].max_irq, + false); =20 - if (!params->no_thread) { - if (data->hist[cpu].thread_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].max_thread); - else - trace_seq_printf(trace->seq, " - "); - } + if (!params->no_thread) + format_summary_value(trace->seq, + data->hist[cpu].thread_count, + data->hist[cpu].max_thread, + false); =20 - if (params->user_hist) { - if (data->hist[cpu].user_count) - trace_seq_printf(trace->seq, "%9llu ", - data->hist[cpu].max_user); - else - trace_seq_printf(trace->seq, " - "); - } + if (params->user_hist) + format_summary_value(trace->seq, + data->hist[cpu].user_count, + data->hist[cpu].max_user, + false); } trace_seq_printf(trace->seq, "\n"); trace_seq_do_printf(trace->seq); @@ -506,16 +503,22 @@ timerlat_print_stats_all(struct timerlat_hist_params = *params, trace_seq_printf(trace->seq, "min: "); =20 if (!params->no_irq) - trace_seq_printf(trace->seq, "%9llu ", - sum.min_irq); + format_summary_value(trace->seq, + sum.irq_count, + sum.min_irq, + false); =20 if (!params->no_thread) - trace_seq_printf(trace->seq, "%9llu ", - sum.min_thread); + format_summary_value(trace->seq, + sum.thread_count, + sum.min_thread, + false); =20 if (params->user_hist) - trace_seq_printf(trace->seq, "%9llu ", - sum.min_user); + format_summary_value(trace->seq, + sum.user_count, + sum.min_user, + false); =20 trace_seq_printf(trace->seq, "\n"); =20 @@ -523,16 +526,22 @@ timerlat_print_stats_all(struct timerlat_hist_params = *params, trace_seq_printf(trace->seq, "avg: "); =20 if (!params->no_irq) - trace_seq_printf(trace->seq, "%9llu ", - sum.sum_irq / sum.irq_count); + format_summary_value(trace->seq, + sum.irq_count, + sum.sum_irq, + true); =20 if (!params->no_thread) - trace_seq_printf(trace->seq, "%9llu ", - sum.sum_thread / sum.thread_count); + format_summary_value(trace->seq, + sum.thread_count, + sum.sum_thread, + true); =20 if (params->user_hist) - trace_seq_printf(trace->seq, "%9llu ", - sum.sum_user / sum.user_count); + format_summary_value(trace->seq, + sum.user_count, + sum.sum_user, + true); =20 trace_seq_printf(trace->seq, "\n"); =20 @@ -540,16 +549,22 @@ timerlat_print_stats_all(struct timerlat_hist_params = *params, trace_seq_printf(trace->seq, "max: "); =20 if (!params->no_irq) - trace_seq_printf(trace->seq, "%9llu ", - sum.max_irq); + format_summary_value(trace->seq, + sum.irq_count, + sum.max_irq, + false); =20 if (!params->no_thread) - trace_seq_printf(trace->seq, "%9llu ", - sum.max_thread); + format_summary_value(trace->seq, + sum.thread_count, + sum.max_thread, + false); =20 if (params->user_hist) - trace_seq_printf(trace->seq, "%9llu ", - sum.max_user); + format_summary_value(trace->seq, + sum.user_count, + sum.max_user, + false); =20 trace_seq_printf(trace->seq, "\n"); trace_seq_do_printf(trace->seq);