From patchwork Thu Jan 30 05:21:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Tse Shao X-Patchwork-Id: 13954322 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 C34A3166307 for ; Thu, 30 Jan 2025 05:27:00 +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=1738214823; cv=none; b=r9b7gWQLiQaVU0qD7N/aS9lZ3j+1REYrd7Zfv+nZrYFW1mvPJf9VJOwTUD+qCV6966DKAOT7z4I4vexp83MhxBQC6xlrc3sNZZAIZmgL5yBcouaqHtUf4Bsm34Vnqz3y5Q7LIN1YTlgB3f6CYiRIEAhuESV9DUi1FCElVZUW06k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214823; c=relaxed/simple; bh=695n3av2Ws9ME+ywo7rKvZ5On177TRKvNDuJu1tpCcU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=B9avmOchWHDgf0QE+KR91LfpIEqEgpqOyH4sLgEb+uaYWEU/ZPcAR2/x7Pow2TSZ06VhEFSNaq9fzRxCuBnNZBO3lkateJ6uv5ycl+6znU9pXrPjRgLiE51kFbOrAw+ohALIxNXEYmD00Gat1LyF7/dvrBdE6h58UJ7G2H6bJuQ= 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.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="iOnpvzE4" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2f5538a2356so817269a91.2 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=LVLI11aJCNcP/cKoYfdU5dL0idSDgiS3Mp2SmN6W5LjFW7JeOAo1P95m7lgtetYR6T Wljramn0pqlxHHTfa6w8QG/6TsDrUa3hWdPjp0yH6yhA+9jK7DxlQkZ14zQa/ZJ3VJ2E tW0plFYMwpHJ7sLEklXdAj0zNIDJPO+diSTzG4FMLiOSD2HO6aIcdkm/XZamZSyhwIbC zi/tbHX394JB4B4FJYaIARrT5lsbxr3tFSxRITubGKUdJ2OW+iXHcMaGF+OftxEJOApl 8EpRthDYc8AZqIJf5eV6fRLIhzkWVU0PrRyKrz3iXEWl3U3c9A4arig2gbcrOWuyfznj LEQA== X-Forwarded-Encrypted: i=1; AJvYcCVOG/2SGBM3bRlGyG+TVlm125Ov1+B3E+HO0ZxkI0baeOkvt+z8mbtCOq70cL3bGdTMPfE=@vger.kernel.org X-Gm-Message-State: AOJu0Yxeth0p1b97UObm54J5x+kLVo7UU3RcoxxiFru3migy0fEdZybk 34S/ncHJ/+M9AdA34GyrF7epBdwcFIbB4l4vZzfyYiuEv+vhHkNMSW7TAvBGFg5K0Tv7+dJ2S+K xkQ== 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: bpf@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 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_lock_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 *con) else bpf_map__set_max_entries(skel->maps.task_data, 1); - 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(u64)); + 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 = con->max_stack; + } + } else { bpf_map__set_max_entries(skel->maps.stacks, 1); + } if (target__has_cpu(target)) { skel->rodata->has_cpu = 1; diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/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"); +/* 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; /* 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_skel/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 +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 is going on. + s32 stack_id; // Identifier for `owner_stat`, which stores as value in `owner_stacks` +}; + struct tstamp_data { u64 timestamp; u64 lock; From patchwork Thu Jan 30 05:21:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Tse Shao X-Patchwork-Id: 13954323 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 A9EF81459E4 for ; Thu, 30 Jan 2025 05:27:28 +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=1738214851; cv=none; b=Z+9WbdtuhUqmwT/Q1ZAVoOTXMIlkKXwtXt/7G/T3M7LFxMvZSvn5GeOCTL02ThgFYwlFRiujrjPhKEcvGHI4TwgBQEqsQjExXxPT3ETHwx4x79v0clbJwxrddAiqVAo7ISjw7ELM2/pJlyC8MNsAW5PKWXe1DoY5YI4AOhsFahQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738214851; c=relaxed/simple; bh=BWJLdGUi3DR8nqjtgdxUOkT7XFxiMervC05OPrIGTOg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=cOKBppIRG6doEkv4SKNg5wBnGicKfJSNBug9KiwZvhfufkkB+fwhREIEu+mYMdxTnmUZilKFTQWQzmiKJ3stQPgNjZ1iCki4c0jWZahXbcDlCy6PH9GdtJhaPGk9NO/e5ydxhbdJj7gCgh+HvACa/0jR3LnncWi+2E14T0qz3rU= 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.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="E6CDnoLw" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2f550d28f7dso839554a91.3 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=lf/wyfmU9lL3BSxlyhBezeO/Q3xNK263LDOyM6V6jxiL2DDVLcrK4iUPTDiq5hl+0s 8JwHCSttyoFF0MOYJFLtQgMsFCvu2OUjV+q6MZxpafHnl+m8YzHqN4WLYKGC3JQFidI2 /E3D2l4lekTmYBI16QqFgweEPvZA6unGoWq4iVdWsKFGWBGfnGoTwpew2a1u+ufTE48b 1WZpeis9kzSvlb32Urg9filsZGxA/Cn5fWUKMy8qvX2HoSasHwd900t43QQfoAoGr42L kXcN2JA86KAt4KhPWj5F0xvEoH+jS0E1fRjyK89djufYtjgjCfu9RCGSEut8mioYv55s g8yg== X-Forwarded-Encrypted: i=1; AJvYcCVibEzWeOISdI1c0i/RZPWBQPVb4/39RN4ZsAiWv6kZbyjE2BzbTpaJ/wp88gHPMmNVswE=@vger.kernel.org X-Gm-Message-State: AOJu0Yz+Rdxf2wOMh30doKV3zUbSFqQi1Wckb1msWmeqb4KFXw/+SPDu kNkEABJYxofnAEqYcNIKqO0Vl4km0W/8CL5k7XbLFSVlUC5F2KcyuQxfbHmnKVvtlU5xC6V00Ci wDA== 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: bpf@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 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` <= 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/util/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; +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(__u32 flags) return pelem; } +static inline s32 get_owner_stack_id(u64 *stacktrace) +{ + s32 *id, new_id; + static s64 id_gen = 1; + + id = bpf_map_lookup_elem(&owner_stacks, stacktrace); + if (id) + return *id; + + new_id = (s32)__sync_fetch_and_add(&id_gen, 1); + + bpf_map_update_elem(&owner_stacks, stacktrace, &new_id, BPF_NOEXIST); + + id = 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 = (__u32)ctx[1]; if (needs_callstack) { + u32 i = 0; + u32 id = 0; + int owner_pid; + u64 *buf; + struct task_struct *task; + struct owner_tracing_data *otdata; + + if (!lock_owner) + goto skip_owner_begin; + + task = get_lock_owner(pelem->lock, pelem->flags); + if (!task) + goto skip_owner_begin; + + owner_pid = BPF_CORE_READ(task, pid); + + buf = bpf_map_lookup_elem(&stack_buf, &i); + if (!buf) + goto skip_owner_begin; + for (i = 0; i < max_stack; i++) + buf[i] = 0x0; + + if (bpf_task_from_pid) { + task = 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 = bpf_map_lookup_elem(&owner_data, &pelem->lock); + id = 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 error and + * just ignore the precvious tracing record. + */ + if (!otdata || otdata->pid != owner_pid) { + struct owner_tracing_data first = { + .pid = owner_pid, + .timestamp = pelem->timestamp, + .count = 1, + .stack_id = 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 != otdata->stack_id) { + u64 duration = otdata->timestamp - pelem->timestamp; + struct contention_key ckey = { + .stack_id = id, + .pid = 0, + .lock_addr_or_cgroup = 0, + }; + struct contention_data *cdata = + bpf_map_lookup_elem(&owner_stat, &ckey); + + if (!cdata) { + struct contention_data first = { + .total_time = duration, + .max_time = duration, + .min_time = duration, + .count = 1, + .flags = 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 = duration; + if (cdata->min_time > duration) + cdata->min_time = duration; + } + + otdata->timestamp = pelem->timestamp; + otdata->stack_id = id; + } + } +skip_owner_begin: pelem->stack_id = 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 = {}; struct contention_data *data; + __u64 timestamp; __u64 duration; bool need_delete = false; @@ -500,12 +615,143 @@ int contention_end(u64 *ctx) need_delete = true; } - duration = bpf_ktime_get_ns() - pelem->timestamp; + timestamp = bpf_ktime_get_ns(); + duration = timestamp - pelem->timestamp; if ((__s64)duration < 0) { __sync_fetch_and_add(&time_fail, 1); goto out; } + if (needs_callstack && lock_owner) { + u64 owner_time; + struct contention_key ckey = {}; + struct contention_data *cdata; + struct owner_tracing_data *otdata; + + otdata = bpf_map_lookup_elem(&owner_data, &pelem->lock); + if (!otdata) + goto skip_owner_end; + + /* Update `owner_stat` */ + owner_time = timestamp - otdata->timestamp; + ckey.stack_id = otdata->stack_id; + cdata = bpf_map_lookup_elem(&owner_stat, &ckey); + + if (!cdata) { + struct contention_data first = { + .total_time = owner_time, + .max_time = owner_time, + .min_time = owner_time, + .count = 1, + .flags = 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 = owner_time; + if (cdata->min_time > owner_time) + cdata->min_time = owner_time; + } + + /* No contention is occurring, delete `lock` entry in `owner_data` */ + if (otdata->count <= 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 = 0; + u64 *buf; + + __sync_fetch_and_add(&otdata->count, -1); + + buf = bpf_map_lookup_elem(&stack_buf, &i); + if (!buf) + goto skip_owner_end; + for (i = 0; i < (u32)max_stack; i++) + buf[i] = 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 = 0; + struct task_struct *task = NULL; + + if (bpf_task_from_pid) + task = 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 = get_owner_stack_id(buf); + + /* + * If owner stack is changed, update `owner_data` and `owner_stat` + * accordingly. + */ + if (id != otdata->stack_id) { + u64 duration = otdata->timestamp - pelem->timestamp; + struct contention_key ckey = { + .stack_id = id, + .pid = 0, + .lock_addr_or_cgroup = 0, + }; + struct contention_data *cdata = + bpf_map_lookup_elem(&owner_stat, &ckey); + + if (!cdata) { + struct contention_data first = { + .total_time = duration, + .max_time = duration, + .min_time = duration, + .count = 1, + .flags = 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 = duration; + if (cdata->min_time > duration) + cdata->min_time = duration; + } + + otdata->timestamp = pelem->timestamp; + otdata->stack_id = id; + } + } + /* + * If ctx[1] is 0, then update tracinng data with the current task, which is + * the new owner. + */ + else { + otdata->pid = pid; + otdata->timestamp = timestamp; + + bpf_get_task_stack(bpf_get_current_task_btf(), buf, + max_stack * sizeof(unsigned long), 0); + otdata->stack_id = get_owner_stack_id(buf); + } + } + } +skip_owner_end: + switch (aggr_mode) { case LOCK_AGGR_CALLER: key.stack_id = pelem->stack_id; From patchwork Thu Jan 30 05:21:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Tse Shao X-Patchwork-Id: 13954324 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 43A3E1459E4 for ; Thu, 30 Jan 2025 05:27:54 +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=1738214876; cv=none; b=RTvhtVyGoczHiz9Ju9YVlS8wHD7QnPfsUzTiZW7dUTwricWeGUCnMCY+TvdS/fxdv50tWWED/QQWzPt1Xb4k5mdiJc+EXgLLKjyzWxjTA90GeARy6/jjtLsjwDs5xP6u8zOfi92jNRCMpkTVXf2GkaihL3NDEXGmImw+dFPyedI= 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.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="crjbuO8n" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2f46b7851fcso1243740a91.1 for ; Wed, 29 Jan 2025 21:27:54 -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=uK92FFDkbqrqJ41IefvV7W2oOuSp01DD4KkUp7KloaNhdkyRXfS4+MlJ8KbVBXyySf DCJmdoNAkFXnwN5laj2Dg1oYRf5vRSu0d7RPSiTPQ1xq3KZT3nIFwZrQdWWXVKsn6rBs pNLqosiCYFnnSeSLZTWvtY4QK2eLlxUeX81f/0/VYND2XiRHcqUMsIdjvX/iPzXjwWp7 bAzXrXesoSVYtrGgExSJweKhxe66R0gtXLDvw2mCVYUduY/6qYkwjzWW6A8AOK3XPIE6 q1L723SsfhL0cNhcysV7Oe7NRX5VuG70D8L8mQlTKYe/4MS17jbpZbLbdNgnJv/EnKIY qXOA== X-Forwarded-Encrypted: i=1; AJvYcCWAhMaZN8TzxAAYFB6bO6/3NqtC7JwrFDviw6CAcJUfht80nsN1by8xzN68WBzmlw/YZk8=@vger.kernel.org X-Gm-Message-State: AOJu0YymppE6JExxJh4/yZIwBc2b84qAncqJq4Zz23iWURc7vsNCTsWM CACYx3P7jsO6eg2exhMT7GIcaLf3Vx6eKTf5kKJ7QUAJGVKkDSjrdg3rU50KsLNSVnJZC6mV3lq wbg== 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: bpf@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 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); } -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 = &result.rb_node; + struct rb_node **rb = &rr->rb_node; struct rb_node *parent = NULL; struct lock_stat *p; - if (combine_locks && st->combined) - return; - while (*rb) { p = container_of(*rb, struct lock_stat, rb); parent = *rb; @@ -439,13 +436,21 @@ static void insert_to_result(struct lock_stat *st, } rb_link_node(&st->rb, parent, rb); - rb_insert_color(&st->rb, &result); + rb_insert_color(&st->rb, rr); } -/* 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 = result.rb_node; + struct rb_node *node = rr->rb_node; if (!node) return NULL; @@ -453,8 +458,15 @@ static struct lock_stat *pop_from_result(void) while (node->rb_left) node = node->rb_left; - 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); } struct trace_lock_handler { From patchwork Thu Jan 30 05:21:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Tse Shao X-Patchwork-Id: 13954325 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 DFB981494D8 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-2ef91d5c863so867802a91.2 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=Se9U4Co8vywAYLgJ4wsd78vRnojbg7ZmMqUoUL2I/aAMNsRFxny4rWg7rFr71kSPK5 3/NHj2/tOkt6zpRhbOzl/VyTfnqX5b7c9QnwUGwcgZtQWtl2hE0ySk2hi+OqtEYrcpgF 5eB6f4RUxfK8dVnvv4d5uOoejjkKcrsJBvjzCwP6DMwdg+IottXZjBN/K6y5jH8IwLy6 oJqvXWueM7G/YKT6XX9t/s/YS0bgHQscs6gESZ5Jq1Xrtq9GaEOL11F1bEVCZZPQZjTi EZ6DujHxarF1IHvBQKg5G5cjx+IdZaqSiuNDBX3PkfVOxG5373qNE1hoIGilehAK3geP /xXg== X-Forwarded-Encrypted: i=1; AJvYcCVEaVB9XsyVG+GX9bxXkHgf4S/rCxqbPBKsTsbRuCFRX0nkn+GwkDfSTwjMvy9b92H5BYw=@vger.kernel.org X-Gm-Message-State: AOJu0YzwtGkLFvM/i0e94XeLsvfkTIrtE2MLMRlZbynZOdnVkPEM8v68 y4mDE4iJL466JrasMpjt/CiZ2aLLZiSfJlBbzaWvALIPw7qt+VjLRWEXVJH3dkyihFzVwb0eAjG rMA== 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: bpf@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 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 bench sched pipe ... contended total wait max wait avg wait type caller 171 1.55 ms 20.26 us 9.06 us mutex pipe_read+0x57 0xffffffffac6318e7 pipe_read+0x57 0xffffffffac623862 vfs_read+0x332 0xffffffffac62434b ksys_read+0xbb 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwframe+0x76 36 193.71 us 15.27 us 5.38 us mutex pipe_write+0x50 0xffffffffac631ee0 pipe_write+0x50 0xffffffffac6241db vfs_write+0x3bb 0xffffffffac6244ab ksys_write+0xbb 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwframe+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_hwframe+0x76 === owner stack trace === 3 31.24 us 15.27 us 10.41 us mutex pipe_read+0x348 0xffffffffac631bd8 pipe_read+0x348 0xffffffffac623862 vfs_read+0x332 0xffffffffac62434b ksys_read+0xbb 0xfffffffface604b2 do_syscall_64+0x82 0xffffffffad00012f entry_SYSCALL_64_after_hwframe+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_contention *con) break; } + if (con->owner && con->save_callstack) { + struct rb_root root = RB_ROOT; + + if (symbol_conf.field_sep) + fprintf(lock_output, "# owner stack trace:\n"); + else + fprintf(lock_output, "\n=== owner stack trace ===\n\n"); + while ((st = pop_owner_stack_trace(con))) + insert_to(&root, st, compare); + + while ((st = pop_from(&root))) { + print_lock_stat(con, st); + zfree(st); + } + } + if (print_nr_entries) { /* update the total/bad stats */ while ((st = pop_from_result())) { @@ -1962,9 +1978,6 @@ static int check_lock_contention_options(const struct option *options, } } - if (show_lock_owner) - show_thread_stats = true; - return 0; } diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_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 lock_contention *con, return name_buf; } +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 = {}; + struct contention_data cdata = {}; + size_t stack_size = con->max_stack * sizeof(*stack_trace); + struct lock_stat *st; + char name[KSYM_NAME_LEN]; + + stacks_fd = bpf_map__fd(skel->maps.owner_stacks); + stat_fd = bpf_map__fd(skel->maps.owner_stat); + if (!stacks_fd || !stat_fd) + return NULL; + + stack_trace = zalloc(stack_size); + if (stack_trace == 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 = stack_id; + bpf_map_lookup_elem(stat_fd, &ckey, &cdata); + + st = 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 = strdup(name); + if (!st->name) + return NULL; + + st->flags = cdata.flags; + st->nr_contended = cdata.count; + st->wait_time_total = cdata.total_time; + st->wait_time_max = cdata.max_time; + st->wait_time_min = cdata.min_time; + st->callstack = stack_trace; + + if (cdata.count) + st->avg_wait_time = 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 = 0; diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-contention.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); +struct lock_stat *pop_owner_stack_trace(struct lock_contention *con); + #else /* !HAVE_BPF_SKEL */ static inline int lock_contention_prepare(struct lock_contention *con __maybe_unused) @@ -187,6 +189,11 @@ static inline int lock_contention_read(struct lock_contention *con __maybe_unuse return 0; } +struct lock_stat *pop_owner_stack_trace(struct lock_contention *con) +{ + return NULL; +} + #endif /* HAVE_BPF_SKEL */ #endif /* PERF_LOCK_CONTENTION_H */ From patchwork Thu Jan 30 05:21:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Tse Shao X-Patchwork-Id: 13954326 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 DF4C214EC73 for ; Thu, 30 Jan 2025 05:28:58 +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=1738214940; cv=none; b=e8lnz0lSs0DwtH4imgkw38eL28D7kklAuzzHWLhuArS7MqeLHqYYwJ0YCrNUIrvCMQ/W8+GANojVUx+1EpvVndDBaSARhAdt2r2HqcWuggNipWWYDzZ9j27i3fu/cjjLghC71zl9M+M0PRxJN6V8onz5hw5FWuw2gahMf/V5lwA= 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.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="bQbWsjfW" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2ee3206466aso2992764a91.1 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=mSxHnnr83RTtiM4PTydg09qUYjxODh1ptB78xZO05vYnH4iWy0CgbkrlZRi/U3XOCm mL8y3je7+zjct/9HCxVKMKtmOQ+51Fz83CrJ1vWs3OJwUomE3H4CD2yGGeM+LuT1MJFf qhWZt6PSVCxJXbKiBabXswdt8qStzklSR64TJaC2IeQu7mfYA1ajN+HUSsjOQ+kL0YVT PQeEiEx+g0qrW27tInbCDgpkiMLQ7ZIZqKkUcBAcoYeGhlGt9lo4GuckwdizNPolvcGl BLnkFfbJXllCSuBdrsUvYdu6mv7xKSZ5BAWwIj7WQaFynEeOE1UIpVG7tg+pHoYM4QSQ YtnQ== X-Forwarded-Encrypted: i=1; AJvYcCXaflqxTnCd6lsQVk9rhbRG/GsdSwcGJ0NfAZyd0b05maTI+bVelJbmEOIBA2kEcPRgT3U=@vger.kernel.org X-Gm-Message-State: AOJu0Yw9I74DGY5PD1XOhIDE30NOEycXqDCA3DAPCpBHL+jybGi86zyI 5qltjfKM0hoYKIgLNy87/rqvSwRiWHwmJBncnsdlCjnL1XvDtJCgxo7ePEG6pie+Yw105D91CDj UEg== 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: bpf@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 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_contention *con) break; } - if (con->owner && con->save_callstack) { + if (con->owner && con->save_callstack && verbose > 0) { struct rb_root root = RB_ROOT; if (symbol_conf.field_sep) @@ -1978,6 +1978,11 @@ static int check_lock_contention_options(const struct option *options, } } + 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; } @@ -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 instead of waiters"), + OPT_BOOLEAN('o', "lock-owner", &show_lock_owner, "show lock owners instead of waiters.\n" + "\t\t\tThis option can be combined with -t, which shows owner's per thread lock stats, or -v, which shows owner's stacktrace"), OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep, "separator", "print result in CSV format with custom separator"), OPT_BOOLEAN(0, "lock-cgroup", &show_lock_cgroups, "show lock stats by cgroup"),