aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_event.h5
-rw-r--r--kernel/perf_event.c30
2 files changed, 16 insertions, 19 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index cdbc2aa64a0b..c6f812e4d058 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -565,6 +565,10 @@ typedef void (*perf_overflow_handler_t)(struct perf_event *, int,
565 struct perf_sample_data *, 565 struct perf_sample_data *,
566 struct pt_regs *regs); 566 struct pt_regs *regs);
567 567
568enum perf_group_flag {
569 PERF_GROUP_SOFTWARE = 0x1,
570};
571
568/** 572/**
569 * struct perf_event - performance event kernel representation: 573 * struct perf_event - performance event kernel representation:
570 */ 574 */
@@ -574,6 +578,7 @@ struct perf_event {
574 struct list_head event_entry; 578 struct list_head event_entry;
575 struct list_head sibling_list; 579 struct list_head sibling_list;
576 int nr_siblings; 580 int nr_siblings;
581 int group_flags;
577 struct perf_event *group_leader; 582 struct perf_event *group_leader;
578 struct perf_event *output; 583 struct perf_event *output;
579 const struct pmu *pmu; 584 const struct pmu *pmu;
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 */
706static 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 */
723static int group_can_go_on(struct perf_event *event, 715static 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