Re: [RFC][PATCH 05/11] perf: register pmu implementations

Frederic Weisbecker
2010-06-28T13:21:01Z

On Thu, Jun 24, 2010 at 04:28:09PM +0200, Peter Zijlstra wrote:
> + if (bp->attr.type != PERF_TYPE_BREAKPOINT)
> + return -ENOENT;
> +
> + err = register_perf_hw_breakpoint(bp);
> + if (err)
> + return err;
> +
> + bp->destroy = bp_perf_event_destroy;

Seems it would make sense to also have destroy in the pmu, it's the same
along every events in the same class right?

But this can be for later.

> +static LIST_HEAD(pmus);
> +static DEFINE_MUTEX(pmus_lock);
> +static struct srcu_struct pmus_srcu;
> +
> +int perf_pmu_register(struct pmu *pmu)
> +{
> + mutex_lock(&pmus_lock);
> + list_add_rcu(&pmu->entry, &pmus);
> + mutex_unlock(&pmus_lock);
> +
> + return 0;
> +}
> +
> +void perf_pmu_unregister(struct pmu *pmu)
> +{
> + mutex_lock(&pmus_lock);
> + list_del_rcu(&pmu->entry);
> + mutex_unlock(&pmus_lock);
>
> - atomic_inc(&perf_swevent_enabled[event_id]);
> - event->destroy = sw_perf_event_destroy;
> + synchronize_srcu(&pmus_srcu);
> +}
> +
> +struct pmu *perf_init_event(struct perf_event *event)
> +{
> + struct pmu *pmu = NULL;
> + int idx;
> +
> + idx = srcu_read_lock(&pmus_srcu);
> + list_for_each_entry_rcu(pmu, &pmus, entry) {
> + int ret = pmu->event_init(event);
> + if (!ret)
> + break;
> + if (ret != -ENOENT) {
> + pmu = ERR_PTR(ret);
> + break;
> }
> - pmu = &perf_ops_generic;
> - break;
> }
> + srcu_read_unlock(&pmus_srcu, idx);
>
> return pmu;
> }

I'm still not sure why all this locking is needed. We don't even
support pmus in modules.

Is there something coming soon that will use this?
I remember something about KVM.

And who will have to use srcu? It seems the event fastpath would
be concerned, right? Will that have an impact on the performances?

> @@ -5743,15 +5742,15 @@ perf_cpu_notify(struct notifier_block *s
> {
> unsigned int cpu = (long)hcpu;
>
> - switch (action) {
> + switch (action & ~CPU_TASKS_FROZEN) {
>
> case CPU_UP_PREPARE:
> - case CPU_UP_PREPARE_FROZEN:
> + case CPU_DOWN_FAILED:
> perf_event_init_cpu(cpu);
> break;
>
> + case CPU_UP_CANCELED:
> case CPU_DOWN_PREPARE:
> - case CPU_DOWN_PREPARE_FROZEN:
> perf_event_exit_cpu(cpu);
> break;

That doesn't seem to be related to this patch initial topic.