diff options
| -rw-r--r-- | include/linux/perf_event.h | 24 | ||||
| -rw-r--r-- | kernel/events/core.c | 6 |
2 files changed, 26 insertions, 4 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 866e85c5eb94..c8ba627c1d60 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -294,9 +294,31 @@ struct ring_buffer; | |||
| 294 | */ | 294 | */ |
| 295 | struct perf_event { | 295 | struct perf_event { |
| 296 | #ifdef CONFIG_PERF_EVENTS | 296 | #ifdef CONFIG_PERF_EVENTS |
| 297 | struct list_head group_entry; | 297 | /* |
| 298 | * entry onto perf_event_context::event_list; | ||
| 299 | * modifications require ctx->lock | ||
| 300 | * RCU safe iterations. | ||
| 301 | */ | ||
| 298 | struct list_head event_entry; | 302 | struct list_head event_entry; |
| 303 | |||
| 304 | /* | ||
| 305 | * XXX: group_entry and sibling_list should be mutually exclusive; | ||
| 306 | * either you're a sibling on a group, or you're the group leader. | ||
| 307 | * Rework the code to always use the same list element. | ||
| 308 | * | ||
| 309 | * Locked for modification by both ctx->mutex and ctx->lock; holding | ||
| 310 | * either sufficies for read. | ||
| 311 | */ | ||
| 312 | struct list_head group_entry; | ||
| 299 | struct list_head sibling_list; | 313 | struct list_head sibling_list; |
| 314 | |||
| 315 | /* | ||
| 316 | * We need storage to track the entries in perf_pmu_migrate_context; we | ||
| 317 | * cannot use the event_entry because of RCU and we want to keep the | ||
| 318 | * group in tact which avoids us using the other two entries. | ||
| 319 | */ | ||
| 320 | struct list_head migrate_entry; | ||
| 321 | |||
| 300 | struct hlist_node hlist_entry; | 322 | struct hlist_node hlist_entry; |
| 301 | int nr_siblings; | 323 | int nr_siblings; |
| 302 | int group_flags; | 324 | int group_flags; |
diff --git a/kernel/events/core.c b/kernel/events/core.c index cb4238e85b38..d49a9d29334c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -7234,15 +7234,15 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) | |||
| 7234 | perf_remove_from_context(event); | 7234 | perf_remove_from_context(event); |
| 7235 | unaccount_event_cpu(event, src_cpu); | 7235 | unaccount_event_cpu(event, src_cpu); |
| 7236 | put_ctx(src_ctx); | 7236 | put_ctx(src_ctx); |
| 7237 | list_add(&event->event_entry, &events); | 7237 | list_add(&event->migrate_entry, &events); |
| 7238 | } | 7238 | } |
| 7239 | mutex_unlock(&src_ctx->mutex); | 7239 | mutex_unlock(&src_ctx->mutex); |
| 7240 | 7240 | ||
| 7241 | synchronize_rcu(); | 7241 | synchronize_rcu(); |
| 7242 | 7242 | ||
| 7243 | mutex_lock(&dst_ctx->mutex); | 7243 | mutex_lock(&dst_ctx->mutex); |
| 7244 | list_for_each_entry_safe(event, tmp, &events, event_entry) { | 7244 | list_for_each_entry_safe(event, tmp, &events, migrate_entry) { |
| 7245 | list_del(&event->event_entry); | 7245 | list_del(&event->migrate_entry); |
| 7246 | if (event->state >= PERF_EVENT_STATE_OFF) | 7246 | if (event->state >= PERF_EVENT_STATE_OFF) |
| 7247 | event->state = PERF_EVENT_STATE_INACTIVE; | 7247 | event->state = PERF_EVENT_STATE_INACTIVE; |
| 7248 | account_event_cpu(event, dst_cpu); | 7248 | account_event_cpu(event, dst_cpu); |
