Messages in this thread | | | Date | Mon, 28 May 2018 13:26:18 +0200 | From | Peter Zijlstra <> | Subject | Re: [RFC 2/2] perf: Sharing PMU counters across compatible events |
| |
On Fri, May 04, 2018 at 04:11:02PM -0700, Song Liu wrote: > +/* > + * If an dup event is already active, add this event as follower, and > + * return 0; otherwise, return -EAGAIN > + * > + * RFC NOTE: this an o(1) operation > + */ > +static int event_dup_try_add_follower(struct perf_event *event, > + struct perf_cpu_context *cpuctx) > +{ > + struct perf_event_dup *pdup; > + > + if (event->dup_id >= cpuctx->dup_event_count) > + return -EAGAIN; > + > + pdup = &cpuctx->dup_event_list[event->dup_id]; > + if (list_empty(&pdup->active_dup)) > + return -EAGAIN; > + > + list_add_tail(&event->dup_sibling_entry, &pdup->active_dup); > + pdup->master->pmu->read(pdup->master); > + event->dup_base_count = pdup_read_count(pdup); > + event->dup_base_child_count = pdup_read_child_count(pdup); > + return 0; > +}
> +/* > + * remove event from the dup list; if it is the master, and there are > + * other active events, promote another event as the new master. > + * > + * return 0, if it is there are more active events in this dup; > + * return -EAGAIN, if it is the last active event > + * > + * RFC NOTE: this an o(1) operation > + */ > +static int event_dup_sched_out(struct perf_event *event, > + struct perf_cpu_context *cpuctx) > +{ > + struct perf_event_dup *pdup; > + > + if (event->dup_id >= cpuctx->dup_event_count) > + return -EAGAIN; > + > + pdup = &cpuctx->dup_event_list[event->dup_id]; > + list_del_init(&event->dup_sibling_entry); > + if (event == pdup->master ) { > + if (list_empty(&pdup->active_dup)) { > + pdup->master = NULL; > + return -EAGAIN;
This one is really odd.. -EAGAIN doesn't make sense for the last event. I see how you got here, but yuck.
> + } else { > + struct perf_event *new_master; > + > + new_master = list_first_entry( > + &cpuctx->dup_event_list[event->dup_id].active_dup, > + struct perf_event, dup_sibling_entry); > + event_dup_sync(new_master, cpuctx); > + pdup_switch_master(pdup, event, new_master); > + pdup->master = new_master; > + } > + } > + return 0; > +}
| |