All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] perf lock contention: Handle error in a single place
@ 2024-08-30  6:51 Namhyung Kim
  2024-08-30  6:51 ` [PATCH 2/3] perf lock contention: Simplify spinlock check Namhyung Kim
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Namhyung Kim @ 2024-08-30  6:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users, Song Liu, bpf

It has some duplicate codes to do the same job.  Let's add a label and
goto there to handle errors in a single place.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/bpf_skel/lock_contention.bpf.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index d931a898c434..e8a6f6463019 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -439,11 +439,8 @@ int contention_end(u64 *ctx)
 
 	duration = bpf_ktime_get_ns() - pelem->timestamp;
 	if ((__s64)duration < 0) {
-		pelem->lock = 0;
-		if (need_delete)
-			bpf_map_delete_elem(&tstamp, &pid);
 		__sync_fetch_and_add(&time_fail, 1);
-		return 0;
+		goto out;
 	}
 
 	switch (aggr_mode) {
@@ -477,11 +474,8 @@ int contention_end(u64 *ctx)
 	data = bpf_map_lookup_elem(&lock_stat, &key);
 	if (!data) {
 		if (data_map_full) {
-			pelem->lock = 0;
-			if (need_delete)
-				bpf_map_delete_elem(&tstamp, &pid);
 			__sync_fetch_and_add(&data_fail, 1);
-			return 0;
+			goto out;
 		}
 
 		struct contention_data first = {
@@ -502,10 +496,7 @@ int contention_end(u64 *ctx)
 				data_map_full = 1;
 			__sync_fetch_and_add(&data_fail, 1);
 		}
-		pelem->lock = 0;
-		if (need_delete)
-			bpf_map_delete_elem(&tstamp, &pid);
-		return 0;
+		goto out;
 	}
 
 	__sync_fetch_and_add(&data->total_time, duration);
@@ -517,6 +508,7 @@ int contention_end(u64 *ctx)
 	if (data->min_time > duration)
 		data->min_time = duration;
 
+out:
 	pelem->lock = 0;
 	if (need_delete)
 		bpf_map_delete_elem(&tstamp, &pid);
-- 
2.46.0.469.g59c65b2a67-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] perf lock contention: Simplify spinlock check
  2024-08-30  6:51 [PATCH 1/3] perf lock contention: Handle error in a single place Namhyung Kim
@ 2024-08-30  6:51 ` Namhyung Kim
  2024-08-30  6:51 ` [PATCH 3/3] perf lock contention: Do not fail EEXIST for update Namhyung Kim
  2024-08-30 13:17 ` [PATCH 1/3] perf lock contention: Handle error in a single place Arnaldo Carvalho de Melo
  2 siblings, 0 replies; 4+ messages in thread
From: Namhyung Kim @ 2024-08-30  6:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users, Song Liu, bpf

The LCB_F_SPIN bit is used for spinlock, rwlock and optimistic spinning
in mutex.  In get_tstamp_elem() it needs to check spinlock and rwlock
only.  As mutex sets the LCB_F_MUTEX, it can check those two bits and
reduce the number of operations.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/bpf_skel/lock_contention.bpf.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index e8a6f6463019..4b7237e178bd 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -323,8 +323,7 @@ static inline struct tstamp_data *get_tstamp_elem(__u32 flags)
 	struct tstamp_data *pelem;
 
 	/* Use per-cpu array map for spinlock and rwlock */
-	if (flags == (LCB_F_SPIN | LCB_F_READ) || flags == LCB_F_SPIN ||
-	    flags == (LCB_F_SPIN | LCB_F_WRITE)) {
+	if ((flags & (LCB_F_SPIN | LCB_F_MUTEX)) == LCB_F_SPIN) {
 		__u32 idx = 0;
 
 		pelem = bpf_map_lookup_elem(&tstamp_cpu, &idx);
-- 
2.46.0.469.g59c65b2a67-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] perf lock contention: Do not fail EEXIST for update
  2024-08-30  6:51 [PATCH 1/3] perf lock contention: Handle error in a single place Namhyung Kim
  2024-08-30  6:51 ` [PATCH 2/3] perf lock contention: Simplify spinlock check Namhyung Kim
@ 2024-08-30  6:51 ` Namhyung Kim
  2024-08-30 13:17 ` [PATCH 1/3] perf lock contention: Handle error in a single place Arnaldo Carvalho de Melo
  2 siblings, 0 replies; 4+ messages in thread
From: Namhyung Kim @ 2024-08-30  6:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users, Song Liu, bpf

When it updates the lock stat for the first time, it needs to create an
element in the BPF hash map.  But if there's a concurrent thread waiting
for the same lock (like for rwsem or rwlock), it might race with the
thread and possibly failed to update with -EEXIST.  In that case, it can
lookup the map again and put the data there instead of failing.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/bpf_skel/lock_contention.bpf.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index 4b7237e178bd..52a876b42699 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -491,6 +491,12 @@ int contention_end(u64 *ctx)
 
 		err = bpf_map_update_elem(&lock_stat, &key, &first, BPF_NOEXIST);
 		if (err < 0) {
+			if (err == -EEXIST) {
+				/* it lost the race, try to get it again */
+				data = bpf_map_lookup_elem(&lock_stat, &key);
+				if (data != NULL)
+					goto found;
+			}
 			if (err == -E2BIG)
 				data_map_full = 1;
 			__sync_fetch_and_add(&data_fail, 1);
@@ -498,6 +504,7 @@ int contention_end(u64 *ctx)
 		goto out;
 	}
 
+found:
 	__sync_fetch_and_add(&data->total_time, duration);
 	__sync_fetch_and_add(&data->count, 1);
 
-- 
2.46.0.469.g59c65b2a67-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/3] perf lock contention: Handle error in a single place
  2024-08-30  6:51 [PATCH 1/3] perf lock contention: Handle error in a single place Namhyung Kim
  2024-08-30  6:51 ` [PATCH 2/3] perf lock contention: Simplify spinlock check Namhyung Kim
  2024-08-30  6:51 ` [PATCH 3/3] perf lock contention: Do not fail EEXIST for update Namhyung Kim
@ 2024-08-30 13:17 ` Arnaldo Carvalho de Melo
  2 siblings, 0 replies; 4+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-08-30 13:17 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
	Ingo Molnar, LKML, linux-perf-users, Song Liu, bpf

On Thu, Aug 29, 2024 at 11:51:48PM -0700, Namhyung Kim wrote:
> It has some duplicate codes to do the same job.  Let's add a label and
> goto there to handle errors in a single place.

Thanks, applied to perf-tools-next,

- Arnaldo
 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/util/bpf_skel/lock_contention.bpf.c | 16 ++++------------
>  1 file changed, 4 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> index d931a898c434..e8a6f6463019 100644
> --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> @@ -439,11 +439,8 @@ int contention_end(u64 *ctx)
>  
>  	duration = bpf_ktime_get_ns() - pelem->timestamp;
>  	if ((__s64)duration < 0) {
> -		pelem->lock = 0;
> -		if (need_delete)
> -			bpf_map_delete_elem(&tstamp, &pid);
>  		__sync_fetch_and_add(&time_fail, 1);
> -		return 0;
> +		goto out;
>  	}
>  
>  	switch (aggr_mode) {
> @@ -477,11 +474,8 @@ int contention_end(u64 *ctx)
>  	data = bpf_map_lookup_elem(&lock_stat, &key);
>  	if (!data) {
>  		if (data_map_full) {
> -			pelem->lock = 0;
> -			if (need_delete)
> -				bpf_map_delete_elem(&tstamp, &pid);
>  			__sync_fetch_and_add(&data_fail, 1);
> -			return 0;
> +			goto out;
>  		}
>  
>  		struct contention_data first = {
> @@ -502,10 +496,7 @@ int contention_end(u64 *ctx)
>  				data_map_full = 1;
>  			__sync_fetch_and_add(&data_fail, 1);
>  		}
> -		pelem->lock = 0;
> -		if (need_delete)
> -			bpf_map_delete_elem(&tstamp, &pid);
> -		return 0;
> +		goto out;
>  	}
>  
>  	__sync_fetch_and_add(&data->total_time, duration);
> @@ -517,6 +508,7 @@ int contention_end(u64 *ctx)
>  	if (data->min_time > duration)
>  		data->min_time = duration;
>  
> +out:
>  	pelem->lock = 0;
>  	if (need_delete)
>  		bpf_map_delete_elem(&tstamp, &pid);
> -- 
> 2.46.0.469.g59c65b2a67-goog

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-08-30 13:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-30  6:51 [PATCH 1/3] perf lock contention: Handle error in a single place Namhyung Kim
2024-08-30  6:51 ` [PATCH 2/3] perf lock contention: Simplify spinlock check Namhyung Kim
2024-08-30  6:51 ` [PATCH 3/3] perf lock contention: Do not fail EEXIST for update Namhyung Kim
2024-08-30 13:17 ` [PATCH 1/3] perf lock contention: Handle error in a single place Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.