|
@@ -937,27 +937,39 @@ list_update_cgroup_event(struct perf_event *event,
|
|
|
if (!is_cgroup_event(event))
|
|
|
return;
|
|
|
|
|
|
- if (add && ctx->nr_cgroups++)
|
|
|
- return;
|
|
|
- else if (!add && --ctx->nr_cgroups)
|
|
|
- return;
|
|
|
/*
|
|
|
* Because cgroup events are always per-cpu events,
|
|
|
* this will always be called from the right CPU.
|
|
|
*/
|
|
|
cpuctx = __get_cpu_context(ctx);
|
|
|
- cpuctx_entry = &cpuctx->cgrp_cpuctx_entry;
|
|
|
- /* cpuctx->cgrp is NULL unless a cgroup event is active in this CPU .*/
|
|
|
- if (add) {
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Since setting cpuctx->cgrp is conditional on the current @cgrp
|
|
|
+ * matching the event's cgroup, we must do this for every new event,
|
|
|
+ * because if the first would mismatch, the second would not try again
|
|
|
+ * and we would leave cpuctx->cgrp unset.
|
|
|
+ */
|
|
|
+ if (add && !cpuctx->cgrp) {
|
|
|
struct perf_cgroup *cgrp = perf_cgroup_from_task(current, ctx);
|
|
|
|
|
|
- list_add(cpuctx_entry, this_cpu_ptr(&cgrp_cpuctx_list));
|
|
|
if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup))
|
|
|
cpuctx->cgrp = cgrp;
|
|
|
- } else {
|
|
|
- list_del(cpuctx_entry);
|
|
|
- cpuctx->cgrp = NULL;
|
|
|
}
|
|
|
+
|
|
|
+ if (add && ctx->nr_cgroups++)
|
|
|
+ return;
|
|
|
+ else if (!add && --ctx->nr_cgroups)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* no cgroup running */
|
|
|
+ if (!add)
|
|
|
+ cpuctx->cgrp = NULL;
|
|
|
+
|
|
|
+ cpuctx_entry = &cpuctx->cgrp_cpuctx_entry;
|
|
|
+ if (add)
|
|
|
+ list_add(cpuctx_entry, this_cpu_ptr(&cgrp_cpuctx_list));
|
|
|
+ else
|
|
|
+ list_del(cpuctx_entry);
|
|
|
}
|
|
|
|
|
|
#else /* !CONFIG_CGROUP_PERF */
|
|
@@ -2489,6 +2501,18 @@ static int __perf_install_in_context(void *info)
|
|
|
raw_spin_lock(&task_ctx->lock);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_CGROUP_PERF
|
|
|
+ if (is_cgroup_event(event)) {
|
|
|
+ /*
|
|
|
+ * If the current cgroup doesn't match the event's
|
|
|
+ * cgroup, we should not try to schedule it.
|
|
|
+ */
|
|
|
+ struct perf_cgroup *cgrp = perf_cgroup_from_task(current, ctx);
|
|
|
+ reprogram = cgroup_is_descendant(cgrp->css.cgroup,
|
|
|
+ event->cgrp->css.cgroup);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
if (reprogram) {
|
|
|
ctx_sched_out(ctx, cpuctx, EVENT_TIME);
|
|
|
add_event_to_ctx(event, ctx);
|