> So the basic issue I mentioned is that: > > > /* > * ,------------------------[1:n]---------------------. > * V V > * perf_event_context <-[1:n]-> perf_event_pmu_context <--- perf_event > * ^ ^ | | > * `--------[1:n]---------' `-[n:1]-> pmu <-[1:n]-' > * > * > * XXX destroy epc when empty > * refcount, !rcu > * > * XXX epc locking > * > * event->pmu_ctx ctx->mutex && inactive > * ctx->pmu_ctx_list ctx->mutex && ctx->lock > * > */ > struct perf_event_pmu_context { > ... > atomic_t refcount; /* event <-> epc */ > ... > } > > But that then also suggests that: > > struct perf_event_context { > ... > refcount_t refcount; > ... > } > > should be: ctx <-> epc, and that is not so, the ctx::refcount still > counts the number of events. > > Now this might not be bad, but it is confusing. I don't have strong opinion, but we store events in ctx, not in pmu_ctx. So, I think it makes sense to keep refcount as ctx <-> event? [...] > +void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) > +{ > + struct perf_event_context *src_ctx, *dst_ctx; > + LIST_HEAD(events); > + > + src_ctx = &per_cpu_ptr(&cpu_context, src_cpu)->ctx; > + dst_ctx = &per_cpu_ptr(&cpu_context, dst_cpu)->ctx; > + > + /* > + * See perf_event_ctx_lock() for comments on the details > + * of swizzling perf_event::ctx. > + */ > + mutex_lock_double(&src_ctx->mutex, &dst_ctx->mutex); > + > + __perf_pmu_remove(src_ctx, src_cpu, pmu, &src_src->pinned_groups, &events); > + __perf_pmu_remove(src_ctx, src_cpu, pmu, &src_src->flexible_groups, &events); Rbtrees does not contain sibling events. Shouldn't we continue using event_list here? Thanks, Ravi