Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp3625182ybz; Mon, 20 Apr 2020 06:32:12 -0700 (PDT) X-Google-Smtp-Source: APiQypIczuzVAXH9s+y14MTW9E1+uNZZFQ4tyE703XDqfWPBdTkBSM+qBssvYDiakZszMa48Xdw/ X-Received: by 2002:a05:6402:19b0:: with SMTP id o16mr14005568edz.162.1587389532439; Mon, 20 Apr 2020 06:32:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587389532; cv=none; d=google.com; s=arc-20160816; b=JINx0NnQ3WPpjeU7ryi/HC7uK6MTQlRfVVu1KNNHJeb/T9NRt2K+Nzp0i7hfrCvD7n 9ox8Hg0TpADj1K5TGtzduJ3aLW8qAgfvP5xpDDVBi5NV3YrSJQsSN7B9RnlduqzeLOGM eOUqYesnd2HC7z/GC1WYoMcICrm835rkQN+fg6poPauUNXGI5PZz3TQSv3olH/FYF2fD yMKtQx8WI6vegmfatePQ8xdRajxYFIWb3UGQVunspxLDCq+j04Eg5OKM/rtmectiRMXx Nv5Mu/NMSHEfQd+gS90LKJ3CZ38U+xlVjDpxGmCWQ6QLaqW+gXwyZPsuZuo7P+yVo1qg yXMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=8by5ooygpRFBTkqvXBtEpZU38N0/chWUXbAOQQUFCdg=; b=hcgfLxQ+8GNuyGD8YXVqMZy2ifWtUNbd0uCXmmUCIUJM9zfYgLX659KETE6oa4h/ac yrx+yqEL4UmVg5GboduCo3E5Vd+uG+1w8/QsLbxYEaA0Htaf8xKfbEmgn5lL9EuwAzgT vZPEIxGDYdEVAH3b7Iiti7C8yk4/oLX9D/My3FqYsSkrKjSgFmuGBJRjuEteMiUl+dDr fwa6cVrWF+trt6zBsvhST3FMaimxHTOpFci3NF+yU1Pn9Lf96Xnb4ACJik+E5Vbq9fOW 4rgw9LVigxN6TTgdbIzUbLwAS6jDyrt97psahguGnCpnVvAQMTpLGZfO7Rc3/QTHjFfX lA8A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=BgoP+I3t; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 31si559874edp.496.2020.04.20.06.31.48; Mon, 20 Apr 2020 06:32:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=BgoP+I3t; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726496AbgDTL5a (ORCPT + 99 others); Mon, 20 Apr 2020 07:57:30 -0400 Received: from mail.kernel.org ([198.145.29.99]:42130 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726491AbgDTL53 (ORCPT ); Mon, 20 Apr 2020 07:57:29 -0400 Received: from quaco.ghostprotocols.net (unknown [179.97.37.151]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DB99622202; Mon, 20 Apr 2020 11:57:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1587383848; bh=VHaBuVImPpmcsEB9xc519IJFBemWJMKz3WiC+S9pBNA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BgoP+I3tlXFrVJpa2CYIDPqFfwTWtPOn0GGWjwcyToXC1PlcQukwSEZKCrhLfvBq+ PzShr+IrlKD4vZdK9xDG+GKxvHZuRLyKb4rdNNhswlQGVTrQDMY9L6+hdLVF3PTG5r DagI+8G9pHJQBdNF5XtWnGLx9cl57NVz+rya3x4E= From: Arnaldo Carvalho de Melo To: Ingo Molnar , Thomas Gleixner Cc: Jiri Olsa , Namhyung Kim , Clark Williams , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Kan Liang , Andi Kleen , Jiri Olsa , Adrian Hunter , Alexey Budankov , Mathieu Poirier , Michael Ellerman , Pavel Gerasimov , Peter Zijlstra , Ravi Bangoria , Stephane Eranian , Vitaly Slobodskoy , Arnaldo Carvalho de Melo Subject: [PATCH 54/60] perf callchain: Save previous cursor nodes for LBR stitching approach Date: Mon, 20 Apr 2020 08:53:10 -0300 Message-Id: <20200420115316.18781-55-acme@kernel.org> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20200420115316.18781-1-acme@kernel.org> References: <20200420115316.18781-1-acme@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kan Liang The cursor nodes which generates from sample are eventually added into callchain. To avoid generating cursor nodes from previous samples again, the previous cursor nodes are also saved for LBR stitching approach. Some option, e.g. hide-unresolved, may hide some LBRs. Add a variable 'valid' in struct callchain_cursor_node to indicate this case. The LBR stitching approach will only append the valid cursor nodes from previous samples later. Signed-off-by: Kan Liang Reviewed-by: Andi Kleen Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexey Budankov Cc: Mathieu Poirier Cc: Michael Ellerman Cc: Namhyung Kim Cc: Pavel Gerasimov Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Stephane Eranian Cc: Vitaly Slobodskoy Link: http://lore.kernel.org/lkml/20200319202517.23423-12-kan.liang@linux.intel.com [ Use zfree() instead of open coded equivalent, and use it when freeing members of structs ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.h | 3 ++ tools/perf/util/machine.c | 76 +++++++++++++++++++++++++++++++++++-- tools/perf/util/thread.h | 8 ++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 706bb7bbe1e1..cb33cd42ff43 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -143,6 +143,9 @@ struct callchain_cursor_node { u64 ip; struct map_symbol ms; const char *srcline; + /* Indicate valid cursor node for LBR stitch */ + bool valid; + bool branch; struct branch_flags branch_flags; u64 branch_from; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index a54ca09a1d00..737dee723a57 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2224,6 +2224,31 @@ static int lbr_callchain_add_kernel_ip(struct thread *thread, return 0; } +static void save_lbr_cursor_node(struct thread *thread, + struct callchain_cursor *cursor, + int idx) +{ + struct lbr_stitch *lbr_stitch = thread->lbr_stitch; + + if (!lbr_stitch) + return; + + if (cursor->pos == cursor->nr) { + lbr_stitch->prev_lbr_cursor[idx].valid = false; + return; + } + + if (!cursor->curr) + cursor->curr = cursor->first; + else + cursor->curr = cursor->curr->next; + memcpy(&lbr_stitch->prev_lbr_cursor[idx], cursor->curr, + sizeof(struct callchain_cursor_node)); + + lbr_stitch->prev_lbr_cursor[idx].valid = true; + cursor->pos++; +} + static int lbr_callchain_add_lbr_ip(struct thread *thread, struct callchain_cursor *cursor, struct perf_sample *sample, @@ -2240,6 +2265,21 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread, int err, i; u64 ip; + /* + * The curr and pos are not used in writing session. They are cleared + * in callchain_cursor_commit() when the writing session is closed. + * Using curr and pos to track the current cursor node. + */ + if (thread->lbr_stitch) { + cursor->curr = NULL; + cursor->pos = cursor->nr; + if (cursor->nr) { + cursor->curr = cursor->first; + for (i = 0; i < (int)(cursor->nr - 1); i++) + cursor->curr = cursor->curr->next; + } + } + if (callee) { /* Add LBR ip from first entries.to */ ip = entries[0].to; @@ -2252,6 +2292,20 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread, if (err) return err; + /* + * The number of cursor node increases. + * Move the current cursor node. + * But does not need to save current cursor node for entry 0. + * It's impossible to stitch the whole LBRs of previous sample. + */ + if (thread->lbr_stitch && (cursor->pos != cursor->nr)) { + if (!cursor->curr) + cursor->curr = cursor->first; + else + cursor->curr = cursor->curr->next; + cursor->pos++; + } + /* Add LBR ip from entries.from one by one. */ for (i = 0; i < lbr_nr; i++) { ip = entries[i].from; @@ -2262,6 +2316,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread, *branch_from); if (err) return err; + save_lbr_cursor_node(thread, cursor, i); } return 0; } @@ -2276,6 +2331,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread, *branch_from); if (err) return err; + save_lbr_cursor_node(thread, cursor, i); } /* Add LBR ip from first entries.to */ @@ -2292,7 +2348,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread, return 0; } -static bool alloc_lbr_stitch(struct thread *thread) +static bool alloc_lbr_stitch(struct thread *thread, unsigned int max_lbr) { if (thread->lbr_stitch) return true; @@ -2301,6 +2357,14 @@ static bool alloc_lbr_stitch(struct thread *thread) if (!thread->lbr_stitch) goto err; + thread->lbr_stitch->prev_lbr_cursor = calloc(max_lbr + 1, sizeof(struct callchain_cursor_node)); + if (!thread->lbr_stitch->prev_lbr_cursor) + goto free_lbr_stitch; + + return true; + +free_lbr_stitch: + zfree(&thread->lbr_stitch); err: pr_warning("Failed to allocate space for stitched LBRs. Disable LBR stitch\n"); thread->lbr_stitch_enable = false; @@ -2319,7 +2383,8 @@ static int resolve_lbr_callchain_sample(struct thread *thread, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, - int max_stack) + int max_stack, + unsigned int max_lbr) { struct ip_callchain *chain = sample->callchain; int chain_nr = min(max_stack, (int)chain->nr), i; @@ -2337,7 +2402,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, return 0; if (thread->lbr_stitch_enable && !sample->no_hw_idx && - alloc_lbr_stitch(thread)) { + (max_lbr > 0) && alloc_lbr_stitch(thread, max_lbr)) { lbr_stitch = thread->lbr_stitch; memcpy(&lbr_stitch->prev_sample, sample, sizeof(*sample)); @@ -2417,8 +2482,11 @@ static int thread__resolve_callchain_sample(struct thread *thread, chain_nr = chain->nr; if (perf_evsel__has_branch_callstack(evsel)) { + struct perf_env *env = perf_evsel__env(evsel); + err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, - root_al, max_stack); + root_al, max_stack, + !env ? 0 : env->max_branches); if (err) return (err < 0) ? err : 0; } diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 34eb61cee6a4..8456174a52c5 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -15,6 +15,7 @@ #include #include "rwsem.h" #include "event.h" +#include "callchain.h" struct addr_location; struct map; @@ -24,6 +25,7 @@ struct unwind_libunwind_ops; struct lbr_stitch { struct perf_sample prev_sample; + struct callchain_cursor_node *prev_lbr_cursor; }; struct thread { @@ -154,6 +156,12 @@ static inline bool thread__is_filtered(struct thread *thread) static inline void thread__free_stitch_list(struct thread *thread) { + struct lbr_stitch *lbr_stitch = thread->lbr_stitch; + + if (!lbr_stitch) + return; + + zfree(&lbr_stitch->prev_lbr_cursor); zfree(&thread->lbr_stitch); } -- 2.21.1