From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754523AbaHAO5G (ORCPT ); Fri, 1 Aug 2014 10:57:06 -0400 Received: from bombadil.infradead.org ([198.137.202.9]:55593 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750851AbaHAO5E (ORCPT ); Fri, 1 Aug 2014 10:57:04 -0400 Date: Fri, 1 Aug 2014 16:56:37 +0200 From: Peter Zijlstra To: Jiri Olsa Cc: linux-kernel@vger.kernel.org, Arnaldo Carvalho de Melo , Corey Ashford , Frederic Weisbecker , Mark Rutland , Paul Mackerras Subject: Re: [PATCH 1/3] perf: Do not allow to create kernel events without handler Message-ID: <20140801145637.GB9918@twins.programming.kicks-ass.net> References: <1406896382-18404-1-git-send-email-jolsa@kernel.org> <1406896382-18404-2-git-send-email-jolsa@kernel.org> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="kZ4UZC+XGJOY4cNK" Content-Disposition: inline In-Reply-To: <1406896382-18404-2-git-send-email-jolsa@kernel.org> User-Agent: Mutt/1.5.21 (2012-12-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --kZ4UZC+XGJOY4cNK Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Aug 01, 2014 at 02:33:00PM +0200, Jiri Olsa wrote: > Force kernel events to specify the handler, because > there's no use for kernel perf event without it. >=20 I think I found a reason; although there is currently no such user, the simple counting events, they don't have overflow handlers at all. I think I did on once, but never merged that code because it was a quick dev hack to create nice changelog numbers etc.. /me goes dig... found it: --- include/linux/perf_event.h | 1=20 kernel/events/core.c | 22 +++++++- kernel/sched/clock.c | 118 ++++++++++++++++++++++++++++++++++++++++= +++++ 3 files changed, 138 insertions(+), 3 deletions(-) --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -561,6 +561,7 @@ extern void perf_pmu_migrate_context(str int src_cpu, int dst_cpu); extern u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running); +extern u64 perf_event_read(struct perf_event *event); =20 =20 struct perf_sample_data { --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2973,15 +2973,31 @@ static inline u64 perf_event_count(struc return local64_read(&event->count) + atomic64_read(&event->child_count); } =20 -static u64 perf_event_read(struct perf_event *event) +u64 perf_event_read(struct perf_event *event) { /* * If event is enabled and currently active on a CPU, update the * value in the event structure: */ if (event->state =3D=3D PERF_EVENT_STATE_ACTIVE) { - smp_call_function_single(event->oncpu, - __perf_event_read, event, 1); + /* + * If the event is for the current task, its guaranteed that we + * never need the cross cpu call, and therefore can allow this + * to be called with IRQs disabled. + * + * Avoids the warning otherwise generated by + * smp_call_function_single(). + */ + if (event->ctx->task =3D=3D current) { + unsigned long flags; + + local_irq_save(flags); + __perf_event_read(event); + local_irq_restore(flags); + } else { + smp_call_function_single(event->oncpu, + __perf_event_read, event, 1); + } } else if (event->state =3D=3D PERF_EVENT_STATE_INACTIVE) { struct perf_event_context *ctx =3D event->ctx; unsigned long flags; --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c @@ -387,3 +387,121 @@ u64 local_clock(void) =20 EXPORT_SYMBOL_GPL(cpu_clock); EXPORT_SYMBOL_GPL(local_clock); + +#include + +static char sched_clock_cache[12*1024*1024]; /* 12M l3 cache */ +static struct perf_event *__sched_clock_cycles; + +static __init u64 sched_clock_cycles(void) +{ + return perf_event_read(__sched_clock_cycles); +} + +static __init noinline void sched_clock_wipe_cache(void) +{ + int i; + + for (i =3D 0; i < sizeof(sched_clock_cache); i++) + ACCESS_ONCE(sched_clock_cache[i]) =3D 0; +} + +static __always_inline u64 cache_cold_clock(u64 (*clock)(void)) +{ + u64 cycles; + + local_irq_disable(); + sched_clock_wipe_cache(); + cycles =3D sched_clock_cycles(); + (void)clock(); + cycles =3D sched_clock_cycles() - cycles; + local_irq_enable(); + + return cycles; +} + +static __init void do_bench(void) +{ + u64 cycles; + u64 tmp; + int i; + + printk("sched_clock_stable: %d\n", sched_clock_stable); + + cycles =3D 0; + for (i =3D 0; i < 1000; i++) + cycles +=3D cache_cold_clock(&sched_clock); + + printk("(cold) sched_clock: %lu\n", cycles); + + cycles =3D 0; + for (i =3D 0; i < 1000; i++) + cycles +=3D cache_cold_clock(&local_clock); + + printk("(cold) local_clock: %lu\n", cycles); + + local_irq_disable(); + ACCESS_ONCE(tmp) =3D sched_clock(); + + cycles =3D sched_clock_cycles(); + + for (i =3D 0; i < 1000; i++) + ACCESS_ONCE(tmp) =3D sched_clock(); + + cycles =3D sched_clock_cycles() - cycles; + local_irq_enable(); + + printk("(warm) sched_clock: %lu\n", cycles); + + local_irq_disable(); + ACCESS_ONCE(tmp) =3D local_clock(); + + cycles =3D sched_clock_cycles(); + + for (i =3D 0; i < 1000; i++) + ACCESS_ONCE(tmp) =3D local_clock(); + + cycles =3D sched_clock_cycles() - cycles; + local_irq_enable(); + + printk("(warm) local_clock: %lu\n", cycles); + + local_irq_disable(); + rdtscll(ACCESS_ONCE(tmp)); + + cycles =3D sched_clock_cycles(); + + for (i =3D 0; i < 1000; i++) + rdtscll(ACCESS_ONCE(tmp)); + + cycles =3D sched_clock_cycles() - cycles; + local_irq_enable(); + + printk("(warm) rdtsc: %lu\n", cycles); +} + +static __init int sched_clock_bench(void) +{ + struct perf_event_attr perf_attr =3D { + .type =3D PERF_TYPE_HARDWARE, + .config =3D PERF_COUNT_HW_CPU_CYCLES, + .size =3D sizeof(struct perf_event_attr), + .pinned =3D 1, + }; + + __sched_clock_cycles =3D perf_event_create_kernel_counter(&perf_attr, -1,= current, NULL, NULL); + + sched_clock_stable =3D 1; + do_bench(); + + sched_clock_stable =3D 0; + do_bench(); + + sched_clock_stable =3D 1; + + perf_event_release_kernel(__sched_clock_cycles); + + return 0; +} + +late_initcall(sched_clock_bench); --kZ4UZC+XGJOY4cNK Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAEBAgAGBQJT26qlAAoJEHZH4aRLwOS6+v4QAJbxKvYcXVPPp9P+8jszLvlx IRY6pP0KmYpOvAP8F89GrxGQWYjWuZVl9+a9RVgqruawR4Z/2WWQRNAr6QstoQ8X 3jij5BGKxHMQwxrxOaEK8Q9YcIlQFMrI0tmAgJjPs6wh66EqLrWFd9ZE+1UHFUuN r2ue1ffFaa0fb/5HOE5x5MbjZnCiD9fGmFZ1yk6BwqjJK6e1bpENNOcvB1ivDiex MG5CYCkDrn0pAePe2ggh559ZZeqISEdFvozhmub600Apnr+Hixufd2QrJiCCN554 RkmsqKWISrQVk+D3lnFFUtAr8VZP9yLhLZ9Qf0RerAtTfkQuuNLtfIvFYD80XO1w e1TgAWMit5qGYuuC8uYbiEduHB0FBry75fX7W3UztZaaJrAixp0vMvQYPLJqZw7R 3JFYOPSxdh7I+6+O6HEQz+goCJe1DCvDoeWlccgIjhTnYiBS8do4Xcjpo0e0tclX SVjoABz+XZI32ClW630VyHhnYDdnim78b035bJsJ7nR5MECix0X60/IvyVGnNMdC Tuy/Wy0tj8IO9541sgK7c+B4ApH3wiAKvwkO7E8XMzagTmlHaKectafnLcfryKS7 XeM1aexyiFW2uPAE52J7SJMD3zR7XXFLPgKIuAV5Hi264JRGxWwN1SPElKdgCZri PcgBtozGpHrq4Q8ZWozy =hDfW -----END PGP SIGNATURE----- --kZ4UZC+XGJOY4cNK--