@@ -4828,6 +4828,11 @@ find_get_pmu_context(struct pmu *pmu, struct perf_event_context *ctx,
4828
4828
void * task_ctx_data = NULL ;
4829
4829
4830
4830
if (!ctx -> task ) {
4831
+ /*
4832
+ * perf_pmu_migrate_context() / __perf_pmu_install_event()
4833
+ * relies on the fact that find_get_pmu_context() cannot fail
4834
+ * for CPU contexts.
4835
+ */
4831
4836
struct perf_cpu_pmu_context * cpc ;
4832
4837
4833
4838
cpc = per_cpu_ptr (pmu -> cpu_pmu_context , event -> cpu );
@@ -12889,6 +12894,9 @@ static void __perf_pmu_install_event(struct pmu *pmu,
12889
12894
int cpu , struct perf_event * event )
12890
12895
{
12891
12896
struct perf_event_pmu_context * epc ;
12897
+ struct perf_event_context * old_ctx = event -> ctx ;
12898
+
12899
+ get_ctx (ctx ); /* normally find_get_context() */
12892
12900
12893
12901
event -> cpu = cpu ;
12894
12902
epc = find_get_pmu_context (pmu , ctx , event );
@@ -12897,6 +12905,11 @@ static void __perf_pmu_install_event(struct pmu *pmu,
12897
12905
if (event -> state >= PERF_EVENT_STATE_OFF )
12898
12906
event -> state = PERF_EVENT_STATE_INACTIVE ;
12899
12907
perf_install_in_context (ctx , event , cpu );
12908
+
12909
+ /*
12910
+ * Now that event->ctx is updated and visible, put the old ctx.
12911
+ */
12912
+ put_ctx (old_ctx );
12900
12913
}
12901
12914
12902
12915
static void __perf_pmu_install (struct perf_event_context * ctx ,
@@ -12935,6 +12948,10 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
12935
12948
struct perf_event_context * src_ctx , * dst_ctx ;
12936
12949
LIST_HEAD (events );
12937
12950
12951
+ /*
12952
+ * Since per-cpu context is persistent, no need to grab an extra
12953
+ * reference.
12954
+ */
12938
12955
src_ctx = & per_cpu_ptr (& perf_cpu_context , src_cpu )-> ctx ;
12939
12956
dst_ctx = & per_cpu_ptr (& perf_cpu_context , dst_cpu )-> ctx ;
12940
12957
0 commit comments