On Sat, Oct 08, 2022 at 11:54:24AM +0530, Ravi Bangoria wrote: > +static void perf_event_swap_task_ctx_data(struct perf_event_context *prev_ctx, > + struct perf_event_context *next_ctx) > +{ > + struct perf_event_pmu_context *prev_epc, *next_epc; > + > + if (!prev_ctx->nr_task_data) > + return; > + > + prev_epc = list_first_entry(&prev_ctx->pmu_ctx_list, > + struct perf_event_pmu_context, > + pmu_ctx_entry); > + next_epc = list_first_entry(&next_ctx->pmu_ctx_list, > + struct perf_event_pmu_context, > + pmu_ctx_entry); > + > + while (&prev_epc->pmu_ctx_entry != &prev_ctx->pmu_ctx_list && > + &next_epc->pmu_ctx_entry != &next_ctx->pmu_ctx_list) { > + > + WARN_ON_ONCE(prev_epc->pmu != next_epc->pmu); > + > + /* > + * PMU specific parts of task perf context can require > + * additional synchronization. As an example of such > + * synchronization see implementation details of Intel > + * LBR call stack data profiling; > + */ > + if (prev_epc->pmu->swap_task_ctx) > + prev_epc->pmu->swap_task_ctx(prev_epc, next_epc); > + else > + swap(prev_epc->task_ctx_data, next_epc->task_ctx_data); Did I forget to advance the iterators here? > + } > +}