From: "Liang, Kan" <kan.liang@linux.intel.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: mingo@redhat.com, tglx@linutronix.de, bp@alien8.de,
acme@kernel.org, namhyung@kernel.org, irogers@google.com,
linux-kernel@vger.kernel.org, ak@linux.intel.com,
eranian@google.com
Subject: Re: [PATCH V8 2/6] perf: attach/detach PMU specific data
Date: Wed, 12 Mar 2025 15:52:06 -0400 [thread overview]
Message-ID: <29655aae-e1fd-4f3a-88f9-033034943ddd@linux.intel.com> (raw)
In-Reply-To: <20250312191823.GB10453@noisy.programming.kicks-ass.net>
On 2025-03-12 3:18 p.m., Peter Zijlstra wrote:
> On Wed, Mar 12, 2025 at 11:25:21AM -0700, kan.liang@linux.intel.com wrote:
>
>> +static int
>> +attach_global_ctx_data(struct kmem_cache *ctx_cache)
>> +{
>> + if (refcount_inc_not_zero(&global_ctx_data_ref))
>> + return 0;
>> +
>> + percpu_down_write(&global_ctx_data_rwsem);
>> + if (!refcount_inc_not_zero(&global_ctx_data_ref)) {
>> + struct task_struct *g, *p;
>> + struct perf_ctx_data *cd;
>> + int ret;
>> +
>> +again:
>> + /* Allocate everything */
>> + rcu_read_lock();
>> + for_each_process_thread(g, p) {
>> + cd = rcu_dereference(p->perf_ctx_data);
>> + if (cd && !cd->global) {
>> + cd->global = 1;
>> + if (!refcount_inc_not_zero(&cd->refcount))
>> + cd = NULL;
>> + }
>> + if (!cd) {
>> + get_task_struct(p);
>> + rcu_read_unlock();
>> +
>> + ret = attach_task_ctx_data(p, ctx_cache, true);
>> + put_task_struct(p);
>> + if (ret) {
>> + __detach_global_ctx_data();
>> + return ret;
>
> AFAICT this returns with global_ctx_data_rwsem taken, no?
Ah, yes
>
>> + }
>> + goto again;
>> + }
>> + }
>> + rcu_read_unlock();
>> +
>> + refcount_set(&global_ctx_data_ref, 1);
>> + }
>> + percpu_up_write(&global_ctx_data_rwsem);
>> +
>> + return 0;
>> +}
>
> Can we rework this with guards? A little something like so?
>
Yes. I will do more test and send a V9.
Thanks,
Kan
> ---
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -5233,18 +5233,20 @@ static refcount_t global_ctx_data_ref;
> static int
> attach_global_ctx_data(struct kmem_cache *ctx_cache)
> {
> + struct task_struct *g, *p;
> + struct perf_ctx_data *cd;
> + int ret;
> +
> if (refcount_inc_not_zero(&global_ctx_data_ref))
> return 0;
>
> - percpu_down_write(&global_ctx_data_rwsem);
> - if (!refcount_inc_not_zero(&global_ctx_data_ref)) {
> - struct task_struct *g, *p;
> - struct perf_ctx_data *cd;
> - int ret;
> + guard(percpu_write)(&global_ctx_data_rwsem);
> + if (refcount_inc_not_zero(&global_ctx_data_ref))
> + return 0;
>
> again:
> - /* Allocate everything */
> - rcu_read_lock();
> + /* Allocate everything */
> + scoped_guard (rcu) {
> for_each_process_thread(g, p) {
> cd = rcu_dereference(p->perf_ctx_data);
> if (cd && !cd->global) {
> @@ -5254,24 +5256,23 @@ attach_global_ctx_data(struct kmem_cache
> }
> if (!cd) {
> get_task_struct(p);
> - rcu_read_unlock();
> -
> - ret = attach_task_ctx_data(p, ctx_cache, true);
> - put_task_struct(p);
> - if (ret) {
> - __detach_global_ctx_data();
> - return ret;
> - }
> - goto again;
> + goto alloc;
> }
> }
> - rcu_read_unlock();
> -
> - refcount_set(&global_ctx_data_ref, 1);
> }
> - percpu_up_write(&global_ctx_data_rwsem);
> +
> + refcount_set(&global_ctx_data_ref, 1);
>
> return 0;
> +
> +alloc:
> + ret = attach_task_ctx_data(p, ctx_cache, true);
> + put_task_struct(p);
> + if (ret) {
> + __detach_global_ctx_data();
> + return ret;
> + }
> + goto again;
> }
>
> static int
> @@ -5338,15 +5339,12 @@ static void detach_global_ctx_data(void)
> if (refcount_dec_not_one(&global_ctx_data_ref))
> return;
>
> - percpu_down_write(&global_ctx_data_rwsem);
> + guard(perpcu_write)(&global_ctx_data_rwsem);
> if (!refcount_dec_and_test(&global_ctx_data_ref))
> - goto unlock;
> + return;
>
> /* remove everything */
> __detach_global_ctx_data();
> -
> -unlock:
> - percpu_up_write(&global_ctx_data_rwsem);
> }
>
> static void detach_perf_ctx_data(struct perf_event *event)
> @@ -8776,9 +8774,9 @@ perf_event_alloc_task_data(struct task_s
> if (!ctx_cache)
> return;
>
> - percpu_down_read(&global_ctx_data_rwsem);
> + guard(percpu_read)(&global_ctx_data_rwsem);
> + guard(rcu)();
>
> - rcu_read_lock();
> cd = rcu_dereference(child->perf_ctx_data);
>
> if (!cd) {
> @@ -8787,21 +8785,16 @@ perf_event_alloc_task_data(struct task_s
> * when attaching the perf_ctx_data.
> */
> if (!refcount_read(&global_ctx_data_ref))
> - goto rcu_unlock;
> + return;
> rcu_read_unlock();
> attach_task_ctx_data(child, ctx_cache, true);
> - goto up_rwsem;
> + return;
> }
>
> if (!cd->global) {
> cd->global = 1;
> refcount_inc(&cd->refcount);
> }
> -
> -rcu_unlock:
> - rcu_read_unlock();
> -up_rwsem:
> - percpu_up_read(&global_ctx_data_rwsem);
> }
>
> void perf_event_fork(struct task_struct *task)
> @@ -13845,9 +13838,8 @@ void perf_event_exit_task(struct task_st
> /*
> * Detach the perf_ctx_data for the system-wide event.
> */
> - percpu_down_read(&global_ctx_data_rwsem);
> + guard(percpu_read)(&global_ctx_data_rwsem);
> detach_task_ctx_data(child);
> - percpu_up_read(&global_ctx_data_rwsem);
> }
>
> static void perf_free_event(struct perf_event *event,
> diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
> index c012df33a9f0..36f3082f2d82 100644
> --- a/include/linux/percpu-rwsem.h
> +++ b/include/linux/percpu-rwsem.h
> @@ -8,6 +8,7 @@
> #include <linux/wait.h>
> #include <linux/rcu_sync.h>
> #include <linux/lockdep.h>
> +#include <linux/cleanup.h>
>
> struct percpu_rw_semaphore {
> struct rcu_sync rss;
> @@ -125,6 +126,13 @@ extern bool percpu_is_read_locked(struct percpu_rw_semaphore *);
> extern void percpu_down_write(struct percpu_rw_semaphore *);
> extern void percpu_up_write(struct percpu_rw_semaphore *);
>
> +DEFINE_GUARD(percpu_read, struct perpcu_rw_semaphore *,
> + perpcu_down_read(_T), percpu_up_read(_T))
> +DEFINE_GUARD_COND(perpcu_read, _try, percpu_down_read_trylock(_T))
> +
> +DEFINE_GUARD(percpu_write, struct percpu_rw_semaphore *,
> + percpu_down_write(_T), perpcu_up_write(_T))
> +
> static inline bool percpu_is_write_locked(struct percpu_rw_semaphore *sem)
> {
> return atomic_read(&sem->block);
>
next prev parent reply other threads:[~2025-03-12 19:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-12 18:25 [PATCH V8 1/6] perf: Save PMU specific data in task_struct kan.liang
2025-03-12 18:25 ` [PATCH V8 2/6] perf: attach/detach PMU specific data kan.liang
2025-03-12 19:18 ` Peter Zijlstra
2025-03-12 19:52 ` Liang, Kan [this message]
2025-03-12 18:25 ` [PATCH V8 3/6] perf: Supply task information to sched_task() kan.liang
2025-03-12 18:25 ` [PATCH V8 4/6] perf/x86/lbr: Fix shorter LBRs call stacks for the system-wide mode kan.liang
2025-03-12 18:25 ` [PATCH V8 5/6] perf/x86: Remove swap_task_ctx() kan.liang
2025-03-12 18:25 ` [PATCH V8 6/6] perf: Clean up pmu specific data kan.liang
2025-03-12 19:05 ` [PATCH V8 1/6] perf: Save PMU specific data in task_struct Peter Zijlstra
2025-03-12 19:41 ` Liang, Kan
2025-03-12 19:43 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=29655aae-e1fd-4f3a-88f9-033034943ddd@linux.intel.com \
--to=kan.liang@linux.intel.com \
--cc=acme@kernel.org \
--cc=ak@linux.intel.com \
--cc=bp@alien8.de \
--cc=eranian@google.com \
--cc=irogers@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox