From nobody Sat May 9 06:01:01 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE26915B554 for ; Thu, 30 Jan 2025 05:27:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214822; cv=none; b=rhZw2UoKxwQSnnk0b8rBuQFX5s0CDz+p83EH6fAbUo8WmbrO7SkqfYXiqpRS6vsA4p9aiGieaNdGLz+WctaMeb7uYYGmC3EVCHvYj/28WHaFJHLvijuY/6EDs2nv2cMIKFU/Xmp4/iHVMCQgXKbppfIWTQaxe25zxA4vGgIEU5w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214822; c=relaxed/simple; bh=695n3av2Ws9ME+ywo7rKvZ5On177TRKvNDuJu1tpCcU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nUQqL2ifBzIMZHIDWsNIc6BDTmoYChrG4sLw9VYDAwbkgIZfOQ0OpZGY8BxK6yIYlxvo3aKfDHJPENvBqE0CPruLuBGqS2kpbcanNhGLw6CH59EJSe5fQXx/P3lGhuK39a1Ab4kZa5c5uaZY815xLqGMSLG/ZLEYw8KG2/HXQNQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=iOnpvzE4; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="iOnpvzE4" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2ef9dbeb848so850031a91.0 for ; Wed, 29 Jan 2025 21:27:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1738214820; x=1738819620; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=YAWsoPYpr8UJoLCc1UNzC9SJcWicZT0vijj00rqMygY=; b=iOnpvzE4HIEp3nCnq01GN0fraZM8LokbNbFhfk86F/xf2Rpj8lZ1z9G18fKBKEhxId V/SyRl3WAIQxuVOztUMu0hF++Y0BGZzv/9ygIG/wHvV0ErzDsQWK22luQ87cZPfOwl2x Dp/vNIPRKqLBqt0AIFA4ULheCcL9KClRnMS4m7xrUgYxkW0NS41M7N/enqfM+6JEZrNz RnlxPK5/ei15xudeuHykN2/cXUmoLplsFw27ywxemDelitbAMW+PjCXqA4XS11jkj9F5 Jh74FuQd0z0hDH0+nyi8wcwlkhTyZLUf6EijYIbfq8HKHAiQxAj2qNGizqv18YsPBv1s qR8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738214820; x=1738819620; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YAWsoPYpr8UJoLCc1UNzC9SJcWicZT0vijj00rqMygY=; b=vhBM2nLwGjSPYKKEVJgsM9RCaVZUa07hYjgyGC5MkJFV351EHTtRVptWfegPPQGySD 4+p2oUGBzbcMWF7PEjuoLpiAcNUKb8MSbLifLlDFuxb4OXmArblMdfx56gfDziB/6/bm 82lLfmHocE56CMNPF0yt7+YY9GfVOTI1MeGvmj34B0bWhPiQ+G9Z8I0JWIafnQcrcBIm TpQiUGL0GW9mITSt1mq6nNYzZJ0kZhNDLo8hy/sw/s9edgEslk6T816ltvOSqnL4Hmpw GE/S6JehuAI3xJXN1B8UsAlFVl36A9dCvvfsganF//AeE07+AxcLpkU4ni+maEVHaapR R+sQ== X-Gm-Message-State: AOJu0YzFNnuU0sR58CQXp63WrIF1pjEf0tPmDocuaRu2fpIye3+ydGls 8+upBjnn/CyuHMgFGo3eTb4mqm6ssIb4dgNL5D3tIpsf14QAYpddMtkCKgEpntv+h1fh7ahH0/q WFsmwBK/v7Q8mSz3XzS9Z528Kab09l9vEqPx86RWr7cuuIL0bj6ykZqC0nOEobUwwGMnBYC5UTv rtQBuVK608u++s0IcQW99LTxaFd4J7h7kP6LQaQ67K X-Google-Smtp-Source: AGHT+IE5EVG9LoIyx9/H31PTLx9FbDo6YtoGlCbR299UqnZwEBWkvRmeaiXUmFgvbV74uOIhaOiGaMmIIiQ= X-Received: from pjbns19.prod.google.com ([2002:a17:90b:2513:b0:2f8:49ad:406c]) (user=ctshao job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:264e:b0:2ee:bbe0:98c6 with SMTP id 98e67ed59e1d1-2f83abb3516mr8517216a91.8.1738214819579; Wed, 29 Jan 2025 21:26:59 -0800 (PST) Date: Wed, 29 Jan 2025 21:21:35 -0800 In-Reply-To: <20250130052510.860318-1-ctshao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250130052510.860318-1-ctshao@google.com> X-Mailer: git-send-email 2.48.1.362.g079036d154-goog Message-ID: <20250130052510.860318-2-ctshao@google.com> Subject: [PATCH v4 1/5] perf lock: Add bpf maps for owner stack tracing From: Chun-Tse Shao To: linux-kernel@vger.kernel.org Cc: Chun-Tse Shao , peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a struct and few bpf maps in order to tracing owner stack. `struct owner_tracing_data`: Contains owner's pid, stack id, timestamp for when the owner acquires lock, and the count of lock waiters. `stack_buf`: Percpu buffer for retrieving owner stacktrace. `owner_stacks`: For tracing owner stacktrace to customized owner stack id. `owner_data`: For tracing lock_address to `struct owner_tracing_data` in bpf program. `owner_stat`: For reporting owner stacktrace in usermode. Signed-off-by: Chun-Tse Shao --- tools/perf/util/bpf_lock_contention.c | 14 ++++++-- .../perf/util/bpf_skel/lock_contention.bpf.c | 33 +++++++++++++++++++ tools/perf/util/bpf_skel/lock_data.h | 7 ++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lo= ck_contention.c index fc8666222399..76542b86e83f 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -131,10 +131,20 @@ int lock_contention_prepare(struct lock_contention *c= on) else bpf_map__set_max_entries(skel->maps.task_data, 1); =20 - if (con->save_callstack) + if (con->save_callstack) { bpf_map__set_max_entries(skel->maps.stacks, con->map_nr_entries); - else + if (con->owner) { + bpf_map__set_value_size(skel->maps.stack_buf, con->max_stack * sizeof(u= 64)); + bpf_map__set_key_size(skel->maps.owner_stacks, + con->max_stack * sizeof(u64)); + bpf_map__set_max_entries(skel->maps.owner_stacks, con->map_nr_entries); + bpf_map__set_max_entries(skel->maps.owner_data, con->map_nr_entries); + bpf_map__set_max_entries(skel->maps.owner_stat, con->map_nr_entries); + skel->rodata->max_stack =3D con->max_stack; + } + } else { bpf_map__set_max_entries(skel->maps.stacks, 1); + } =20 if (target__has_cpu(target)) { skel->rodata->has_cpu =3D 1; diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/ut= il/bpf_skel/lock_contention.bpf.c index 6533ea9b044c..23fe9cc980ae 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -27,6 +27,38 @@ struct { __uint(max_entries, MAX_ENTRIES); } stacks SEC(".maps"); =20 +/* buffer for owner stacktrace */ +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u64)); + __uint(max_entries, 1); +} stack_buf SEC(".maps"); + +/* a map for tracing owner stacktrace to owner stack id */ +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u64)); // owner stacktrace + __uint(value_size, sizeof(__s32)); // owner stack id + __uint(max_entries, 1); +} owner_stacks SEC(".maps"); + +/* a map for tracing lock address to owner data */ +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u64)); // lock address + __uint(value_size, sizeof(struct owner_tracing_data)); + __uint(max_entries, 1); +} owner_data SEC(".maps"); + +/* a map for contention_key (stores owner stack id) to contention data */ +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(struct contention_key)); + __uint(value_size, sizeof(struct contention_data)); + __uint(max_entries, 1); +} owner_stat SEC(".maps"); + /* maintain timestamp at the beginning of contention */ struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -143,6 +175,7 @@ const volatile int needs_callstack; const volatile int stack_skip; const volatile int lock_owner; const volatile int use_cgroup_v2; +const volatile int max_stack; =20 /* determine the key of lock stat */ const volatile int aggr_mode; diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_ske= l/lock_data.h index c15f734d7fc4..15f5743bd409 100644 --- a/tools/perf/util/bpf_skel/lock_data.h +++ b/tools/perf/util/bpf_skel/lock_data.h @@ -3,6 +3,13 @@ #ifndef UTIL_BPF_SKEL_LOCK_DATA_H #define UTIL_BPF_SKEL_LOCK_DATA_H =20 +struct owner_tracing_data { + u32 pid; // Who has the lock. + u32 count; // How many waiters for this lock. + u64 timestamp; // The time while the owner acquires lock and contention i= s going on. + s32 stack_id; // Identifier for `owner_stat`, which stores as value in `o= wner_stacks` +}; + struct tstamp_data { u64 timestamp; u64 lock; --=20 2.48.1.362.g079036d154-goog From nobody Sat May 9 06:01:01 2026 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4D802CAB for ; Thu, 30 Jan 2025 05:27:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214850; cv=none; b=TnqTD4C6Q8IGCm8JnbJDft2nbTOkgcvz9cEysHvVfNURocQlZOl0iQID659/UE+irL8M795L1SiCJXthl80S5caCVZRPk8j0IyRS+Ev+cTmOlGCC4TFZ3lR636LgRu1wVuWPTMcEXOFPKoZMQBCIS4cEsl4CGWPQJur2r3wgpr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214850; c=relaxed/simple; bh=BWJLdGUi3DR8nqjtgdxUOkT7XFxiMervC05OPrIGTOg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=pC/39haamR66LkD8Eo9TnTUGapobEDuaH/kMWgqcG3S9rsyKI5KODBJEck3/65e/zbkynepCFhhc0Ywuhs591pf+hWxPavWPp0CvmoeBMmPpu4hqcMf7EO3mI64WG9Za2HBnkKzamu3pVHmmbJyloEytvqo03uw0fJhjeYbK/pU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=E6CDnoLw; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="E6CDnoLw" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2ef7fbd99a6so856447a91.1 for ; Wed, 29 Jan 2025 21:27:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1738214848; x=1738819648; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Eoz4oz6QTxUbKv6q8SfAmVVJoB+ud0WDRT/FEIrl2tc=; b=E6CDnoLwG2BGXgHus8u5jjCm6cA0ecgdBDlbk82NLpIpb63CIPs9Vt/DDmqjJmrPWk P52uheH25g+VfqYBBiYCuNhQcec4plWadqtDCKgFeKoP3fxAY2v87t5G1zG4BXZVjlMq C+lXnvV3NaP8afoKqe64+PmtbfZZdJ1bPJQUnoshqPfLB6yObsikhumonNzhupOrekdb rl+mEEHeRzakFzSss/UNQBdB2D2rafqNdo8Lvqyi11hcKrPF69WXyPUv6JKz3TdEV6dm TQ6AUBszhsTrYRCLy8JXg4twJf8rREvHYCXjullA4/cPtbz0psVHSJNigfR0P9rksw/M Ig2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738214848; x=1738819648; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Eoz4oz6QTxUbKv6q8SfAmVVJoB+ud0WDRT/FEIrl2tc=; b=BDYB8eCM4NHF6LZlj+l8Fn38y82sOhKO6ukwFvW9Dsa9zUrPxGEiOKjClLTXKksGQa NQskOK0xj9bSrhCXbu2qRFasf7mrLNlIWbsODDfcFWA+gca+eFtAtjk853RUmmaDWCL6 t0SqahE4TWf0tndnWIPa0/DrdH3A0E6oNt6A/++4KZOkkAJjGlOJgBBA8luZJ05Jv4b3 CKGuRbovb78lOZoRXRvBnBjr1zs+lWbC4e6dT8NaxAvDFL7jyYUElnq6qnLPJnJbJrfJ 781Ybnjp2Ci62kuWLpPMkMc4xl2+1Dpro/wKqR0yBdJjO39BNkmRUJ2PPiaThzT7qSQj QLig== X-Gm-Message-State: AOJu0YzJLbJzRs9jLCF56p6+tY7jEiur+/gGaNJTG09+Z2hzDBj7qGH4 VWaXycBFeyBQA0ml5DJr2se1KMYhgdL0QVJIkMeAfa0xhBvSuvkbyVXLcJWz2+B+0bXvwsPX2/h AsWb1Lw9WhaHQHKAIIC05t6kBaRUWj+fdqW6LA2kb+oXHBKKlsVnYIsqpUbMuVbMT98qTDS4m1V x8xk1jQBwX7Pcb8TBIP9fHWv/v20TEV1Wa1YDvwM+Z X-Google-Smtp-Source: AGHT+IEp83k/grfwaYq18R2r97tjxPvE5EzL6rrbuFZMp0feyMOdZ7+5wQ3HO7vFOBbKXK/kNVnwCR1Bnzs= X-Received: from pjbtc5.prod.google.com ([2002:a17:90b:5405:b0:2e2:9f67:1ca3]) (user=ctshao job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2749:b0:2ee:ba84:5cac with SMTP id 98e67ed59e1d1-2f83abab6b5mr9464321a91.7.1738214848248; Wed, 29 Jan 2025 21:27:28 -0800 (PST) Date: Wed, 29 Jan 2025 21:21:36 -0800 In-Reply-To: <20250130052510.860318-1-ctshao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250130052510.860318-1-ctshao@google.com> X-Mailer: git-send-email 2.48.1.362.g079036d154-goog Message-ID: <20250130052510.860318-3-ctshao@google.com> Subject: [PATCH v4 2/5] perf lock: Retrieve owner callstack in bpf program From: Chun-Tse Shao To: linux-kernel@vger.kernel.org Cc: Chun-Tse Shao , peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Tracks lock contention by tracing owner callstacks in `contention_begin()` and `contention_end()`, storing data in the owner_stat BPF map. `contention_begin()` records the owner and their callstack. `contention_end()` updates contention statistics (count, time), decrements the waiter count, and removes the record when no waiters remain. Statistics are also updated if the owner's callstack changes. Note that owner and its callstack retrieval may fail. To elaborate the process in detail: /* * In `contention_begin(), the current task is the lock waiter`. We * create/update `owner_data` for the given `lock` address. contention_begin() { Try to get owner task. Skip entire process if fails. Try to get owner stack based on task. Use empty stack if fails. Store owner stack into `owner_stacks` and create `stack_id`. If fail to store, use negative `stack_id`, which will be ignored while reporting in usermode. Retrieve `owner_tracing_data` in `owner_data` with given `lock` address. /* * The first case means contention just happens, or mismatched owner * infomation so we just drop the previous record. */ if (`owner_tracing_data` does not exist || the recorded owner `pid` does not match with the detected owner) { Create `owner_tracing_data` with info from detected owner, and store it in `owner_data` with key `lock` address. } /* * The second case means contention is on going. One more waiter is * joining the lock contention. Both `owner_data` and `owner_stat` * should be updated. */ else { `owner_tracing_data.count`++ Create `contention_key` with owner `stack_id` and lookup `contention_data` in `owner_stat`. if (`contention_data` does not exist) { Create new entry for `contention_key`:`contention_data` in `owner_stat`. } else { Update the `count` and `total_time` in existing `contention_data`. } Update `timestamp` and `stack_id` in `owner_tracing_data`. } } /* * In `contention_end()`, the current task will be the new owner of * the `lock`, if `ctx[1]` is not 0. */ contention_end() { Lookup `owner_tracing_data` in `owner_data` with key `lock`. Create `contention_key` with `owner_tracing_data.stack_id` and lookup `contention_data` in `owner_stat`. if (`contention_data` does not exist) { Create new entry for `contention_key`:`contention_data` in `owner_stat`. } else { Update the `count` and `total_time` in existing `contention_data`. } /* * There is no more waiters, contention is over, delete the record. */ if (`owner_tracing_data.count` <=3D 1) { delete this record in `owner_data`. } /* * Contention is still on going. */ else { `owner_tracing_data.count`-- if (`!ctx[0]`) { The current task exits without acquiring the lock. However we check for the recorded owner if the stack is changed, and update `onwer_data` and `owner_stat` accordingly. } else { The current task is the new owner, retrieve its stack, store it in `owner_stack` and update `owner_tracing_data`. } } } Signed-off-by: Chun-Tse Shao --- .../perf/util/bpf_skel/lock_contention.bpf.c | 248 +++++++++++++++++- 1 file changed, 247 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/ut= il/bpf_skel/lock_contention.bpf.c index 23fe9cc980ae..b12df873379f 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -197,6 +197,9 @@ int data_fail; int task_map_full; int data_map_full; =20 +struct task_struct *bpf_task_from_pid(s32 pid) __ksym __weak; +void bpf_task_release(struct task_struct *p) __ksym __weak; + static inline __u64 get_current_cgroup_id(void) { struct task_struct *task; @@ -420,6 +423,26 @@ static inline struct tstamp_data *get_tstamp_elem(__u3= 2 flags) return pelem; } =20 +static inline s32 get_owner_stack_id(u64 *stacktrace) +{ + s32 *id, new_id; + static s64 id_gen =3D 1; + + id =3D bpf_map_lookup_elem(&owner_stacks, stacktrace); + if (id) + return *id; + + new_id =3D (s32)__sync_fetch_and_add(&id_gen, 1); + + bpf_map_update_elem(&owner_stacks, stacktrace, &new_id, BPF_NOEXIST); + + id =3D bpf_map_lookup_elem(&owner_stacks, stacktrace); + if (id) + return *id; + + return -1; +} + SEC("tp_btf/contention_begin") int contention_begin(u64 *ctx) { @@ -437,6 +460,97 @@ int contention_begin(u64 *ctx) pelem->flags =3D (__u32)ctx[1]; =20 if (needs_callstack) { + u32 i =3D 0; + u32 id =3D 0; + int owner_pid; + u64 *buf; + struct task_struct *task; + struct owner_tracing_data *otdata; + + if (!lock_owner) + goto skip_owner_begin; + + task =3D get_lock_owner(pelem->lock, pelem->flags); + if (!task) + goto skip_owner_begin; + + owner_pid =3D BPF_CORE_READ(task, pid); + + buf =3D bpf_map_lookup_elem(&stack_buf, &i); + if (!buf) + goto skip_owner_begin; + for (i =3D 0; i < max_stack; i++) + buf[i] =3D 0x0; + + if (bpf_task_from_pid) { + task =3D bpf_task_from_pid(owner_pid); + if (task) { + bpf_get_task_stack(task, buf, max_stack * sizeof(unsigned long), 0); + bpf_task_release(task); + } + } + + otdata =3D bpf_map_lookup_elem(&owner_data, &pelem->lock); + id =3D get_owner_stack_id(buf); + + /* + * Contention just happens, or corner case `lock` is owned by process not + * `owner_pid`. For the corner case we treat it as unexpected internal e= rror and + * just ignore the precvious tracing record. + */ + if (!otdata || otdata->pid !=3D owner_pid) { + struct owner_tracing_data first =3D { + .pid =3D owner_pid, + .timestamp =3D pelem->timestamp, + .count =3D 1, + .stack_id =3D id, + }; + bpf_map_update_elem(&owner_data, &pelem->lock, &first, BPF_ANY); + } + /* Contention is ongoing and new waiter joins */ + else { + __sync_fetch_and_add(&otdata->count, 1); + + /* + * The owner is the same, but stacktrace might be changed. In this case= we + * store/update `owner_stat` based on current owner stack id. + */ + if (id !=3D otdata->stack_id) { + u64 duration =3D otdata->timestamp - pelem->timestamp; + struct contention_key ckey =3D { + .stack_id =3D id, + .pid =3D 0, + .lock_addr_or_cgroup =3D 0, + }; + struct contention_data *cdata =3D + bpf_map_lookup_elem(&owner_stat, &ckey); + + if (!cdata) { + struct contention_data first =3D { + .total_time =3D duration, + .max_time =3D duration, + .min_time =3D duration, + .count =3D 1, + .flags =3D pelem->flags, + }; + bpf_map_update_elem(&owner_stat, &ckey, &first, + BPF_NOEXIST); + } else { + __sync_fetch_and_add(&cdata->total_time, duration); + __sync_fetch_and_add(&cdata->count, 1); + + /* FIXME: need atomic operations */ + if (cdata->max_time < duration) + cdata->max_time =3D duration; + if (cdata->min_time > duration) + cdata->min_time =3D duration; + } + + otdata->timestamp =3D pelem->timestamp; + otdata->stack_id =3D id; + } + } +skip_owner_begin: pelem->stack_id =3D bpf_get_stackid(ctx, &stacks, BPF_F_FAST_STACK_CMP | stack_skip); if (pelem->stack_id < 0) @@ -473,6 +587,7 @@ int contention_end(u64 *ctx) struct tstamp_data *pelem; struct contention_key key =3D {}; struct contention_data *data; + __u64 timestamp; __u64 duration; bool need_delete =3D false; =20 @@ -500,12 +615,143 @@ int contention_end(u64 *ctx) need_delete =3D true; } =20 - duration =3D bpf_ktime_get_ns() - pelem->timestamp; + timestamp =3D bpf_ktime_get_ns(); + duration =3D timestamp - pelem->timestamp; if ((__s64)duration < 0) { __sync_fetch_and_add(&time_fail, 1); goto out; } =20 + if (needs_callstack && lock_owner) { + u64 owner_time; + struct contention_key ckey =3D {}; + struct contention_data *cdata; + struct owner_tracing_data *otdata; + + otdata =3D bpf_map_lookup_elem(&owner_data, &pelem->lock); + if (!otdata) + goto skip_owner_end; + + /* Update `owner_stat` */ + owner_time =3D timestamp - otdata->timestamp; + ckey.stack_id =3D otdata->stack_id; + cdata =3D bpf_map_lookup_elem(&owner_stat, &ckey); + + if (!cdata) { + struct contention_data first =3D { + .total_time =3D owner_time, + .max_time =3D owner_time, + .min_time =3D owner_time, + .count =3D 1, + .flags =3D pelem->flags, + }; + bpf_map_update_elem(&owner_stat, &ckey, &first, BPF_NOEXIST); + } else { + __sync_fetch_and_add(&cdata->total_time, owner_time); + __sync_fetch_and_add(&cdata->count, 1); + + /* FIXME: need atomic operations */ + if (cdata->max_time < owner_time) + cdata->max_time =3D owner_time; + if (cdata->min_time > owner_time) + cdata->min_time =3D owner_time; + } + + /* No contention is occurring, delete `lock` entry in `owner_data` */ + if (otdata->count <=3D 1) + bpf_map_delete_elem(&owner_data, &pelem->lock); + /* + * Contention is still ongoing, with a new owner (current task). `owner_= data` + * should be updated accordingly. + */ + else { + u32 i =3D 0; + u64 *buf; + + __sync_fetch_and_add(&otdata->count, -1); + + buf =3D bpf_map_lookup_elem(&stack_buf, &i); + if (!buf) + goto skip_owner_end; + for (i =3D 0; i < (u32)max_stack; i++) + buf[i] =3D 0x0; + + /* + * ctx[1] has the return code of the lock function. + * If ctx[1] is not 0, the current task terminates lock waiting without + * acquiring it. Owner is not changed, but we still need to update the = owner + * stack. + */ + if (!ctx[1]) { + s32 id =3D 0; + struct task_struct *task =3D NULL; + + if (bpf_task_from_pid) + task =3D bpf_task_from_pid(otdata->pid); + + if (task) { + bpf_get_task_stack(task, buf, + max_stack * sizeof(unsigned long), 0); + bpf_task_release(task); + } + + id =3D get_owner_stack_id(buf); + + /* + * If owner stack is changed, update `owner_data` and `owner_stat` + * accordingly. + */ + if (id !=3D otdata->stack_id) { + u64 duration =3D otdata->timestamp - pelem->timestamp; + struct contention_key ckey =3D { + .stack_id =3D id, + .pid =3D 0, + .lock_addr_or_cgroup =3D 0, + }; + struct contention_data *cdata =3D + bpf_map_lookup_elem(&owner_stat, &ckey); + + if (!cdata) { + struct contention_data first =3D { + .total_time =3D duration, + .max_time =3D duration, + .min_time =3D duration, + .count =3D 1, + .flags =3D pelem->flags, + }; + bpf_map_update_elem(&owner_stat, &ckey, &first, + BPF_NOEXIST); + } else { + __sync_fetch_and_add(&cdata->total_time, duration); + __sync_fetch_and_add(&cdata->count, 1); + + /* FIXME: need atomic operations */ + if (cdata->max_time < duration) + cdata->max_time =3D duration; + if (cdata->min_time > duration) + cdata->min_time =3D duration; + } + + otdata->timestamp =3D pelem->timestamp; + otdata->stack_id =3D id; + } + } + /* + * If ctx[1] is 0, then update tracinng data with the current task, whi= ch is + * the new owner. + */ + else { + otdata->pid =3D pid; + otdata->timestamp =3D timestamp; + + bpf_get_task_stack(bpf_get_current_task_btf(), buf, + max_stack * sizeof(unsigned long), 0); + otdata->stack_id =3D get_owner_stack_id(buf); + } + } + } +skip_owner_end: + switch (aggr_mode) { case LOCK_AGGR_CALLER: key.stack_id =3D pelem->stack_id; --=20 2.48.1.362.g079036d154-goog From nobody Sat May 9 06:01:01 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D0F0224F0 for ; Thu, 30 Jan 2025 05:27:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214876; cv=none; b=DNQg0HOQwafLXbMt+524g3biFT/aG03TcuCFip6DO7sRf82+xEBUnO/f+WprfkJRaP2gxZfARquz4PKP046wjN0aA2PCFZwh5tF8+H+SzQ5iLOqm+lNDKTVp5pfV83BXQ5aMmoNK4wjIUxfNQtnQbahVBYyC3sgljdees9qtZrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214876; c=relaxed/simple; bh=Ht42p/R3GvLPsEkGjA4DAAVNTKk7SjZobV1MMBLi7PI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TiCy/qd1WOxDlWpEAF3cTR5mBbB60qWHJUC6Vm/5Q4Jzy4RjVPteMD7BX0IHVLqfkVAePc5K58G5ZZPH4hd4I6ugLzH9nux2lT5cbO/A2S5hNMPk4AVhgSVUi/QHZkYSXIlr3/6dzOunQ8lxT9Wf+NosfhcbtT60eN+B7dghw00= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=crjbuO8n; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="crjbuO8n" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2ef909597d9so1217000a91.3 for ; Wed, 29 Jan 2025 21:27:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1738214874; x=1738819674; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=lZWmWQKUD35icTNF3HhWFGiCoHcg7wGDsZidgu9Msnk=; b=crjbuO8n1PMExqmUF/R8hbdwQcIGaoujUGGLLkJZDIWzq6QcruUG+V4JOZRUa1de7c M06O1tuDPq9c6G1+uT858Xdp/er1LlrZIcdGtCDFzg+ObS6EWIMx2CDpvPlrRyZxt2ti NTW09S+JGnEkmh9bPuKk7ztX91cdWT0IgNE/9UzE8ENKPWCUJ6HP2KTDZljFwFE5CruY 42Dari9wXscyYGce4f6cp4G+AFYfTIFPxOsESguZYIId2IfNRL8ytqcAV0WmAz1J/0q9 A5bfIqUZ23RXKKi6oKkHu8CiLGwQLqvWYaDLx6QOGmAta61910MxylNiVrR6+EzUDzPF XC5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738214874; x=1738819674; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lZWmWQKUD35icTNF3HhWFGiCoHcg7wGDsZidgu9Msnk=; b=TGkc509GVY6lmKL2Rct5mhQ53RinIxXerCnfqfz6B4uhuG1rcTo4kX/kjxWSVA496c PQEAC+CqBa7R5xczYZBJ+GYLFFZ1OSg2YmOrXgf/4S49EcmFhmy8EPM31h1DWJIcgXlh S/N9hxTf9rnDEzV4ErzeoblrtRrHc98DK1ynMZSMPCwWs9616hp5Bo3ceIsV6viTp6SF j1EUJZzeoWQKP48G/uo0LF5euv8pdyK8OZ45/cbsJPsXetxBGkJYpIPG3ZGzajVVRiP/ UkkcrzfetcchR9bQ8V6pXTqfvN+u6j9fUFp24Kwham8HgGN1eTf4h4vN77qfbugwcdfG 5sNg== X-Gm-Message-State: AOJu0YyWL3O/ZPVFMbLcvXfz/RwCo2/2Pu03aKd5GuZ9jryeZNUxGE1/ guHlsKLD7v557FARljI5qhgyB+H4FUzIoNyThIujvasHxl73vd/sCsbJJBtxEF68PyAGQ/P6D+z 9om9vf1T+DrkiGNHnml0kmQFUJu+A3QnrcxzEP12L2hilZ47NmztFnM3TgVxLhQTvI66Q0NRWfV OArBYFCeJvVu80PCT56M+CejCvVIMXuUKr3C1+cY9n X-Google-Smtp-Source: AGHT+IFTGGMJDvsDA2u5yz62HGQdtvml8XGOC02A1JQSSppiaRkgKuKOZukXXfRh7ajMa8jwe35GDum78Gs= X-Received: from pjbtb14.prod.google.com ([2002:a17:90b:53ce:b0:2e0:aba3:662a]) (user=ctshao job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:1c03:b0:2ee:d18c:7d84 with SMTP id 98e67ed59e1d1-2f83ac17ebemr8179710a91.20.1738214874459; Wed, 29 Jan 2025 21:27:54 -0800 (PST) Date: Wed, 29 Jan 2025 21:21:37 -0800 In-Reply-To: <20250130052510.860318-1-ctshao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250130052510.860318-1-ctshao@google.com> X-Mailer: git-send-email 2.48.1.362.g079036d154-goog Message-ID: <20250130052510.860318-4-ctshao@google.com> Subject: [PATCH v4 3/5] perf lock: Make rb_tree helper functions generic From: Chun-Tse Shao To: linux-kernel@vger.kernel.org Cc: Chun-Tse Shao , peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The rb_tree helper functions can be reused for parsing `owner_lock_stat` into rb tree for sorting. Signed-off-by: Chun-Tse Shao --- tools/perf/builtin-lock.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 5d405cd8e696..9bebc186286f 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -418,16 +418,13 @@ static void combine_lock_stats(struct lock_stat *st) rb_insert_color(&st->rb, &sorted); } =20 -static void insert_to_result(struct lock_stat *st, - int (*bigger)(struct lock_stat *, struct lock_stat *)) +static void insert_to(struct rb_root *rr, struct lock_stat *st, + int (*bigger)(struct lock_stat *, struct lock_stat *)) { - struct rb_node **rb =3D &result.rb_node; + struct rb_node **rb =3D &rr->rb_node; struct rb_node *parent =3D NULL; struct lock_stat *p; =20 - if (combine_locks && st->combined) - return; - while (*rb) { p =3D container_of(*rb, struct lock_stat, rb); parent =3D *rb; @@ -439,13 +436,21 @@ static void insert_to_result(struct lock_stat *st, } =20 rb_link_node(&st->rb, parent, rb); - rb_insert_color(&st->rb, &result); + rb_insert_color(&st->rb, rr); } =20 -/* returns left most element of result, and erase it */ -static struct lock_stat *pop_from_result(void) +static inline void insert_to_result(struct lock_stat *st, + int (*bigger)(struct lock_stat *, + struct lock_stat *)) +{ + if (combine_locks && st->combined) + return; + insert_to(&result, st, bigger); +} + +static inline struct lock_stat *pop_from(struct rb_root *rr) { - struct rb_node *node =3D result.rb_node; + struct rb_node *node =3D rr->rb_node; =20 if (!node) return NULL; @@ -453,8 +458,15 @@ static struct lock_stat *pop_from_result(void) while (node->rb_left) node =3D node->rb_left; =20 - rb_erase(node, &result); + rb_erase(node, rr); return container_of(node, struct lock_stat, rb); + +} + +/* returns left most element of result, and erase it */ +static struct lock_stat *pop_from_result(void) +{ + return pop_from(&result); } =20 struct trace_lock_handler { --=20 2.48.1.362.g079036d154-goog From nobody Sat May 9 06:01:01 2026 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DFBE8155322 for ; Thu, 30 Jan 2025 05:28:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214912; cv=none; b=WXK+4ysaaNuLmVTQz96qVjh06q7nh/OUae+hRRF2IywANJ91Fh7iQrvdarx/z5Cdh2rTdwJ0Z1YjM3B1giVlMr8m4BKtYwalHbVfJIIgWlm3S18kUsEgn+hbYxgX+3SX7T7ktl3Rc3+igBg1UOba1cMRJ79WKXgbTYZhn+WuV78= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214912; c=relaxed/simple; bh=NH6skItZvtRN3wH8ru69yeLyhrXA6+M2n5XBGwhpNnQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YZwt4MtAe04KSgpdy07c9hk2IJN4SblXI0yDdPdkYxqa44qs+rMm+Wl/OgKC3XVrklENkxuk/tMVPq3wcX50mO8RV1Vq10aZjyAI+mLgZGH37FWo9AqdWeRwBLXezSLizyMZLVaUpuQQom7mcpedMFafkA6leRKU/lNBuRTjj5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=RjgnTggM; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="RjgnTggM" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2ee5668e09bso864942a91.3 for ; Wed, 29 Jan 2025 21:28:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1738214910; x=1738819710; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=AOkrsQudmNHuJicI5VzkKDKtJxBuPweX3eG0BmVtZ1U=; b=RjgnTggMhxNQ4xxaC08f3LsOl554mRvuob/pjsExI2v+vQKF4JvKQIMZEtpspiQ7Jk dHh/cJkYNiVPnDlMTG8FQDt6/e3aYchaGIU4K86mQNi14jjpOJJU0+1dhQwESs+r/Ni/ Qq2PShpk64DVQ5T/jvhtMw53n1Xf0BMNLIE3tyZUnH0L9zC6MuWEmx+xI/02LdlzOoti zG55Y44m8Gq1KsCMVx1LRZTAN8braPVb7rjXZ7Mo0Urk3P38wzmLfm95975Mz0K9KdNZ wxDA0rtKwpXJn03+HUuVTdgSo8uaU6CTqJ0cDEIXzjPpbCIhOhGFmhryIGqzRcJHirgl DA4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738214910; x=1738819710; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=AOkrsQudmNHuJicI5VzkKDKtJxBuPweX3eG0BmVtZ1U=; b=ZcI6wUCJBU4MsxUWnM7F5uyKZ1ENnuBUcJNqgme0TSy+DCmShbX/jZcN8/gEJsWKNa rPy0j/ia4+GeFcj4c1CXqORaOpreaN8heUOQG7GK27SuDbKkhMVxts/sibDlw8r3D2NE /Oytnv4WkBXzZLCo4zSc0B2zaKc8zVs6dem08ecZ7nFSUa/ofE1HaRM35zAXGougRXiT hxC4IstJn54uTuEWuLdFOLtNOqXQ33sj1o0Jc4x80StrP0His5PlDqIQHI8k7HPg/YHL 9NmWHFeLxHJIc6oGVg5CJYc91UrgVnJLYcphZGx4GdSEBUjyhC9Nzw235Sfe5PYy26TV 8/cw== X-Gm-Message-State: AOJu0Yxhmo2XC3SfRsMg/WVcWO7s5yMeWSrQJ9qew9Dc6RkK6ih90I8c oV+nFX/G1BbunHAbgj9BxFx3VlJYcfO5yiD0nbAKYrVu7Vgkthm5vj4x8pR8ZnLgExZcmxEQpzx fdH13zEQq99TkNjW3IKKabQ7UysVFnHIi4+PP5DmxAzSaf/vTwtcueok94nBM1IGQnibEdBboAl MuY/mjFct7oRdP1iJ3Dsj30h+m9CM+QyNHC7JYMNKR X-Google-Smtp-Source: AGHT+IGjL+7WMzTrhfufcEmRgWouNlOrrvV6Wm7UCA6RKy8zDkkuZV2wYzUIhagUPOo40tkAdIlTVHToXPI= X-Received: from pjbtb14.prod.google.com ([2002:a17:90b:53ce:b0:2e0:aba3:662a]) (user=ctshao job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:fc47:b0:2ee:863e:9ff6 with SMTP id 98e67ed59e1d1-2f83ac0920bmr9546052a91.16.1738214910213; Wed, 29 Jan 2025 21:28:30 -0800 (PST) Date: Wed, 29 Jan 2025 21:21:38 -0800 In-Reply-To: <20250130052510.860318-1-ctshao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250130052510.860318-1-ctshao@google.com> X-Mailer: git-send-email 2.48.1.362.g079036d154-goog Message-ID: <20250130052510.860318-5-ctshao@google.com> Subject: [PATCH v4 4/5] perf lock: Report owner stack in usermode From: Chun-Tse Shao To: linux-kernel@vger.kernel.org Cc: Chun-Tse Shao , peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Parse `owner_lock_stat` into a rb tree, and report owner lock stats with stack trace in order. Example output: $ sudo ~/linux/tools/perf/perf lock con -abvo -Y mutex-spin -E3 perf benc= h sched pipe ... contended total wait max wait avg wait type caller 171 1.55 ms 20.26 us 9.06 us mutex pipe_rea= d+0x57 0xffffffffac6318e7 pipe_read+0x57 0xffffffffac623862 vfs_read+0x332 0xffffffffac62434b ksys_read+0xbb 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwfram= e+0x76 36 193.71 us 15.27 us 5.38 us mutex pipe_wri= te+0x50 0xffffffffac631ee0 pipe_write+0x50 0xffffffffac6241db vfs_write+0x3bb 0xffffffffac6244ab ksys_write+0xbb 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwfram= e+0x76 4 51.22 us 16.47 us 12.80 us mutex do_epoll= _wait+0x24d 0xffffffffac691f0d do_epoll_wait+0x24d 0xffffffffac69249b do_epoll_pwait.part.0+0xb 0xffffffffac693ba5 __x64_sys_epoll_pwait+0x95 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwfram= e+0x76 =3D=3D=3D owner stack trace =3D=3D=3D 3 31.24 us 15.27 us 10.41 us mutex pipe_rea= d+0x348 0xffffffffac631bd8 pipe_read+0x348 0xffffffffac623862 vfs_read+0x332 0xffffffffac62434b ksys_read+0xbb 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwfram= e+0x76 ... Signed-off-by: Chun-Tse Shao --- tools/perf/builtin-lock.c | 19 ++++++++-- tools/perf/util/bpf_lock_contention.c | 54 +++++++++++++++++++++++++++ tools/perf/util/lock-contention.h | 7 ++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 9bebc186286f..3dc100cf30ef 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -1817,6 +1817,22 @@ static void print_contention_result(struct lock_cont= ention *con) break; } =20 + if (con->owner && con->save_callstack) { + struct rb_root root =3D RB_ROOT; + + if (symbol_conf.field_sep) + fprintf(lock_output, "# owner stack trace:\n"); + else + fprintf(lock_output, "\n=3D=3D=3D owner stack trace =3D=3D=3D\n\n"); + while ((st =3D pop_owner_stack_trace(con))) + insert_to(&root, st, compare); + + while ((st =3D pop_from(&root))) { + print_lock_stat(con, st); + zfree(st); + } + } + if (print_nr_entries) { /* update the total/bad stats */ while ((st =3D pop_from_result())) { @@ -1962,9 +1978,6 @@ static int check_lock_contention_options(const struct= option *options, } } =20 - if (show_lock_owner) - show_thread_stats =3D true; - return 0; } =20 diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lo= ck_contention.c index 76542b86e83f..dc83b02c9724 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -549,6 +549,60 @@ static const char *lock_contention_get_name(struct loc= k_contention *con, return name_buf; } =20 +struct lock_stat *pop_owner_stack_trace(struct lock_contention *con) +{ + int stacks_fd, stat_fd; + u64 *stack_trace; + s32 stack_id; + struct contention_key ckey =3D {}; + struct contention_data cdata =3D {}; + size_t stack_size =3D con->max_stack * sizeof(*stack_trace); + struct lock_stat *st; + char name[KSYM_NAME_LEN]; + + stacks_fd =3D bpf_map__fd(skel->maps.owner_stacks); + stat_fd =3D bpf_map__fd(skel->maps.owner_stat); + if (!stacks_fd || !stat_fd) + return NULL; + + stack_trace =3D zalloc(stack_size); + if (stack_trace =3D=3D NULL) + return NULL; + + if (bpf_map_get_next_key(stacks_fd, NULL, stack_trace)) + return NULL; + + bpf_map_lookup_elem(stacks_fd, stack_trace, &stack_id); + ckey.stack_id =3D stack_id; + bpf_map_lookup_elem(stat_fd, &ckey, &cdata); + + st =3D zalloc(sizeof(struct lock_stat)); + if (!st) + return NULL; + + strcpy(name, + stack_trace[0] ? lock_contention_get_name(con, NULL, stack_trace, = 0) : "unknown"); + + st->name =3D strdup(name); + if (!st->name) + return NULL; + + st->flags =3D cdata.flags; + st->nr_contended =3D cdata.count; + st->wait_time_total =3D cdata.total_time; + st->wait_time_max =3D cdata.max_time; + st->wait_time_min =3D cdata.min_time; + st->callstack =3D stack_trace; + + if (cdata.count) + st->avg_wait_time =3D cdata.total_time / cdata.count; + + bpf_map_delete_elem(stacks_fd, stack_trace); + bpf_map_delete_elem(stat_fd, &ckey); + + return st; +} + int lock_contention_read(struct lock_contention *con) { int fd, stack, err =3D 0; diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-conte= ntion.h index a09f7fe877df..97fd33c57f17 100644 --- a/tools/perf/util/lock-contention.h +++ b/tools/perf/util/lock-contention.h @@ -168,6 +168,8 @@ int lock_contention_stop(void); int lock_contention_read(struct lock_contention *con); int lock_contention_finish(struct lock_contention *con); =20 +struct lock_stat *pop_owner_stack_trace(struct lock_contention *con); + #else /* !HAVE_BPF_SKEL */ =20 static inline int lock_contention_prepare(struct lock_contention *con __ma= ybe_unused) @@ -187,6 +189,11 @@ static inline int lock_contention_read(struct lock_con= tention *con __maybe_unuse return 0; } =20 +struct lock_stat *pop_owner_stack_trace(struct lock_contention *con) +{ + return NULL; +} + #endif /* HAVE_BPF_SKEL */ =20 #endif /* PERF_LOCK_CONTENTION_H */ --=20 2.48.1.362.g079036d154-goog From nobody Sat May 9 06:01:01 2026 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 19E9E1714A5 for ; Thu, 30 Jan 2025 05:28:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214940; cv=none; b=P2TEg6r1ceiaXyCr3YwhO3x3c1TiJiEfV9iYKpo3ie4C/VggbjutRScC6Om4tuNfVvMlMg7tnCEbSUt4ps+uCXefc2h9aLYmSJrzCOxo5iezR/5ecTEstaaH0YhLkx3p+oke2q2kdt4+HMyifDpL5vr60TzQcMlEu+pwrJ6pL94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214940; c=relaxed/simple; bh=u6YkVusD/Op7sqnbvcd5wk9G8T1i8o928y5G6z6230Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=j5jRlLzbb8a7bAVUcFLQruwh3wOBMfm5HHMMVVntMS567eiWifbMsZSFc1lf2huBB+GtYPhCzeE6G9GKpULJFgKygpuJrirMAhKLHWir/RV3KPf831Ca9Zgdwbceir8LOqF8tBtDqNV95G75AwYVdUPqr887S6PHVBRnuZMbI7s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=bQbWsjfW; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ctshao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bQbWsjfW" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2efa0eb9cfeso876302a91.0 for ; Wed, 29 Jan 2025 21:28:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1738214938; x=1738819738; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=+0ShH9N5Xn6KPuPHJxS7CDMVtVwzvZCJ66gbSr17EIs=; b=bQbWsjfWDiiBc437PwMiY3W+X8Y/xqCxzfik1FMZyZUl6M51Ih+YjNrC0IK1t5UinZ jtjjHe+P0wQY/0iE0OH7V8SxZHGwzgVNcXS9fSypWtb8S4xccVXxn43SK3n5TmrcKNNP bo0Df8pSmrb2Gupahpnfp9nCXbNF1CP5gl3SsrP89voqqH0KC1FDT+NdVB1CcOcBuLtL k7+18RZ8NQ1CO+sip31TCI+hbDQHfY9nR8+0OlEr+XivwEw2Zw4S5No0EwScsBrs88iG n8YZArMzpR/rnOiypT4IvF17QjyDUX6P6GPL4QOyTqHOyvDYYneaNXuAEi40uYeTMRNq XEnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738214938; x=1738819738; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+0ShH9N5Xn6KPuPHJxS7CDMVtVwzvZCJ66gbSr17EIs=; b=MNP0L5Hqpj4TZ9n0zKXACeURW4GOUmsRulsLuZKNWqrSRpurjj9RiSjn5yj49xBVpN Cfuts74lnOEyxmGsDwVo4ya0A7Uo8BVeEh3P9Lfs3sq+CBU4xL2PMWFyW/2x5f7hyFLa BdkfrMdTrwzvjDYd8u56dri188I8UXBjdFo23qgaiyfcJOpywAPU2KYmRETe7vE3tUCD moW4c72+0sVhaBTwxMgRIqwueHF+52VKFCgJRzC/IyFdbeNz5Qe62/PhIrRaNd7lCagO l/IalvmUDC8QxC6GQ9uoHTeM47z1CA0W/pwHvglXpxp2usyGqo1R/6OOAJ7Oh3DhgePZ yldA== X-Gm-Message-State: AOJu0YxnPlhdujLFqSiFekRBAk58A//FlSQNzOcAbqPBs3D2xBFozNHl vp7lEIwZ3cSPZclwKejFWfLsxFV7FKcgIlnuZOZUvM0nCyFn8ntQJZXzyxqGrz6MPFwvmubPmu1 JBuSx+dEfdpEPPFyDPE7DfTPrAf9aXyr4/ilDm+qnTP/qMDO2NeE1rLcRXv2CRUWBNS1cN6RYiQ WNLVzgpL3hqBTT8/hJGxgdL8o82wH6ATWcJEjgDlCv X-Google-Smtp-Source: AGHT+IGAa4sALHMHuka14HUWGEWJicF6lkEI38f6YBOpiimEmEVwBwfSoQdPngmhzipeF6VwLNy0lnnvIIA= X-Received: from pjboi16.prod.google.com ([2002:a17:90b:3a10:b0:2da:5868:311c]) (user=ctshao job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:518b:b0:2ee:8cbb:de28 with SMTP id 98e67ed59e1d1-2f846388b5cmr3469102a91.8.1738214938246; Wed, 29 Jan 2025 21:28:58 -0800 (PST) Date: Wed, 29 Jan 2025 21:21:39 -0800 In-Reply-To: <20250130052510.860318-1-ctshao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250130052510.860318-1-ctshao@google.com> X-Mailer: git-send-email 2.48.1.362.g079036d154-goog Message-ID: <20250130052510.860318-6-ctshao@google.com> Subject: [PATCH v4 5/5] perf lock: Update documentation for -o option in contention mode From: Chun-Tse Shao To: linux-kernel@vger.kernel.org Cc: Chun-Tse Shao , peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch also decouple -o with -t, and shows warning to notify the new behavior for -ov. Signed-off-by: Chun-Tse Shao --- tools/perf/builtin-lock.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 3dc100cf30ef..e16bda6ce525 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -1817,7 +1817,7 @@ static void print_contention_result(struct lock_conte= ntion *con) break; } =20 - if (con->owner && con->save_callstack) { + if (con->owner && con->save_callstack && verbose > 0) { struct rb_root root =3D RB_ROOT; =20 if (symbol_conf.field_sep) @@ -1978,6 +1978,11 @@ static int check_lock_contention_options(const struc= t option *options, } } =20 + if (show_lock_owner && !show_thread_stats) { + pr_warning("Now -o try to show owner's callstack instead of pid and comm= .\n"); + pr_warning("Please use -t option too to keep the old behavior.\n"); + } + return 0; } =20 @@ -2569,7 +2574,8 @@ int cmd_lock(int argc, const char **argv) "Filter specific address/symbol of locks", parse_lock_addr), OPT_CALLBACK('S', "callstack-filter", NULL, "NAMES", "Filter specific function in the callstack", parse_call_stack), - OPT_BOOLEAN('o', "lock-owner", &show_lock_owner, "show lock owners instea= d of waiters"), + OPT_BOOLEAN('o', "lock-owner", &show_lock_owner, "show lock owners instea= d of waiters.\n" + "\t\t\tThis option can be combined with -t, which shows owner's per thre= ad lock stats, or -v, which shows owner's stacktrace"), OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep, "separ= ator", "print result in CSV format with custom separator"), OPT_BOOLEAN(0, "lock-cgroup", &show_lock_cgroups, "show lock stats by cgr= oup"), --=20 2.48.1.362.g079036d154-goog