diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/perf_event.c | 30 |
1 files changed, 11 insertions, 19 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index bbebe2832639..eae6ff693604 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -315,9 +315,16 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx) | |||
315 | if (group_leader == event) { | 315 | if (group_leader == event) { |
316 | struct list_head *list; | 316 | struct list_head *list; |
317 | 317 | ||
318 | if (is_software_event(event)) | ||
319 | event->group_flags |= PERF_GROUP_SOFTWARE; | ||
320 | |||
318 | list = ctx_group_list(event, ctx); | 321 | list = ctx_group_list(event, ctx); |
319 | list_add_tail(&event->group_entry, list); | 322 | list_add_tail(&event->group_entry, list); |
320 | } else { | 323 | } else { |
324 | if (group_leader->group_flags & PERF_GROUP_SOFTWARE && | ||
325 | !is_software_event(event)) | ||
326 | group_leader->group_flags &= ~PERF_GROUP_SOFTWARE; | ||
327 | |||
321 | list_add_tail(&event->group_entry, &group_leader->sibling_list); | 328 | list_add_tail(&event->group_entry, &group_leader->sibling_list); |
322 | group_leader->nr_siblings++; | 329 | group_leader->nr_siblings++; |
323 | } | 330 | } |
@@ -372,6 +379,9 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx) | |||
372 | list = ctx_group_list(event, ctx); | 379 | list = ctx_group_list(event, ctx); |
373 | list_move_tail(&sibling->group_entry, list); | 380 | list_move_tail(&sibling->group_entry, list); |
374 | sibling->group_leader = sibling; | 381 | sibling->group_leader = sibling; |
382 | |||
383 | /* Inherit group flags from the previous leader */ | ||
384 | sibling->group_flags = event->group_flags; | ||
375 | } | 385 | } |
376 | } | 386 | } |
377 | 387 | ||
@@ -700,24 +710,6 @@ group_error: | |||
700 | } | 710 | } |
701 | 711 | ||
702 | /* | 712 | /* |
703 | * Return 1 for a group consisting entirely of software events, | ||
704 | * 0 if the group contains any hardware events. | ||
705 | */ | ||
706 | static int is_software_only_group(struct perf_event *leader) | ||
707 | { | ||
708 | struct perf_event *event; | ||
709 | |||
710 | if (!is_software_event(leader)) | ||
711 | return 0; | ||
712 | |||
713 | list_for_each_entry(event, &leader->sibling_list, group_entry) | ||
714 | if (!is_software_event(event)) | ||
715 | return 0; | ||
716 | |||
717 | return 1; | ||
718 | } | ||
719 | |||
720 | /* | ||
721 | * Work out whether we can put this event group on the CPU now. | 713 | * Work out whether we can put this event group on the CPU now. |
722 | */ | 714 | */ |
723 | static int group_can_go_on(struct perf_event *event, | 715 | static int group_can_go_on(struct perf_event *event, |
@@ -727,7 +719,7 @@ static int group_can_go_on(struct perf_event *event, | |||
727 | /* | 719 | /* |
728 | * Groups consisting entirely of software events can always go on. | 720 | * Groups consisting entirely of software events can always go on. |
729 | */ | 721 | */ |
730 | if (is_software_only_group(event)) | 722 | if (event->group_flags & PERF_GROUP_SOFTWARE) |
731 | return 1; | 723 | return 1; |
732 | /* | 724 | /* |
733 | * If an exclusive group is already on, no other hardware | 725 | * If an exclusive group is already on, no other hardware |