[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CACT4Y+bW1gpv8bz0vswaVUt-OB07oJ3NBeTi+vchAe8TTWK+mg@mail.gmail.com>
Date: Sun, 31 Jan 2021 11:04:43 +0100
From: Dmitry Vyukov <dvyukov@...gle.com>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Ingo Molnar <mingo@...hat.com>,
Arnaldo Carvalho de Melo <acme@...nel.org>,
Mark Rutland <mark.rutland@....com>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
Jiri Olsa <jolsa@...hat.com>,
Namhyung Kim <namhyung@...nel.org>,
Will Deacon <will@...nel.org>,
LKML <linux-kernel@...r.kernel.org>,
Matt Morehouse <mascasa@...gle.com>
Subject: Re: Process-wide watchpoints
On Thu, Nov 12, 2020 at 11:43 AM Dmitry Vyukov <dvyukov@...gle.com> wrote:
> > > for sampling race detection),
> > > number of threads in the process can be up to, say, ~~10K and the
> > > watchpoint is intended to be set for a very brief period of time
> > > (~~few ms).
> >
> > Performance is a consideration here, doing lots of IPIs in such a short
> > window, on potentially large machines is a DoS risk.
> >
> > > This can be done today with both perf_event_open and ptrace.
> > > However, the problem is that both APIs work on a single thread level
> > > (? perf_event_open can be inherited by children, but not for existing
> > > siblings). So doing this would require iterating over, say, 10K
> >
> > One way would be to create the event before the process starts spawning
> > threads and keeping it disabled. Then every thread will inherit it, but
> > it'll be inactive.
> >
> > > I see at least one potential problem: what do we do if some sibling
> > > thread already has all 4 watchpoints consumed?
> >
> > That would be immediately avoided by this, since it will have the
> > watchpoint reserved per inheriting the event.
> >
> > Then you can do ioctl(PERF_EVENT_IOC_{MODIFY_ATTRIBUTES,ENABLE,DISABLE})
> > to update the watch location and enable/disable it. This _will_ indeed
> > result in a shitload of IPIs if the threads are active, but it should
> > work.
>
> Aha! That's the possibility I missed.
> We will try to prototype this and get back with more questions if/when
> we have them.
> Thanks!
Hi Peter,
I've tested this approach and it works, but only in half.
PERF_EVENT_IOC_{ENABLE,DISABLE} work as advertised.
However, PERF_EVENT_IOC_MODIFY_ATTRIBUTES does not work for inherited
child events.
Does something like this make any sense to you? Are you willing to
accept such change?
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 55d18791a72d..f6974807a32c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3174,7 +3174,7 @@ int perf_event_refresh(struct perf_event *event,
int refresh)
}
EXPORT_SYMBOL_GPL(perf_event_refresh);
-static int perf_event_modify_breakpoint(struct perf_event *bp,
+static int _perf_event_modify_breakpoint(struct perf_event *bp,
struct perf_event_attr *attr)
{
int err;
@@ -3189,6 +3189,28 @@ static int perf_event_modify_breakpoint(struct
perf_event *bp,
return err;
}
+static int perf_event_modify_breakpoint(struct perf_event *bp,
+ struct perf_event_attr *attr)
+{
+ struct perf_event *child;
+ int err;
+
+ WARN_ON_ONCE(bp->ctx->parent_ctx);
+
+ mutex_lock(&bp->child_mutex);
+ err = _perf_event_modify_breakpoint(bp, attr);
+ if (err)
+ goto unlock;
+ list_for_each_entry(child, &bp->child_list, child_list) {
+ err = _perf_event_modify_breakpoint(child, attr);
+ if (err)
+ goto unlock;
+ }
+unlock:
+ mutex_unlock(&bp->child_mutex);
+ return err;
+}
+
static int perf_event_modify_attr(struct perf_event *event,
struct perf_event_attr *attr)
Powered by blists - more mailing lists