Skip to content

Commit 170ca9a

Browse files
committed
perf/core: Invert perf_read_group() loops
jira LE-1907 Rebuild_History Non-Buildable kernel-3.10.0-514.el7 commit-author Peter Zijlstra <[email protected]> commit fa8c269 In order to enable the use of perf_event_read(.group = true), we need to invert the sibling-child loop nesting of perf_read_group(). Currently we iterate the child list for each sibling, this precludes using group reads. Flip things around so we iterate each group for each child. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> [ Made the patch compile and things. ] Signed-off-by: Sukadev Bhattiprolu <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vince Weaver <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]> (cherry picked from commit fa8c269) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 817df70 commit 170ca9a

File tree

1 file changed

+55
-30
lines changed

1 file changed

+55
-30
lines changed

kernel/events/core.c

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3778,50 +3778,75 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
37783778
}
37793779
EXPORT_SYMBOL_GPL(perf_event_read_value);
37803780

3781-
static int perf_read_group(struct perf_event *event,
3782-
u64 read_format, char __user *buf)
3781+
static void __perf_read_group_add(struct perf_event *leader,
3782+
u64 read_format, u64 *values)
37833783
{
3784-
struct perf_event *leader = event->group_leader, *sub;
3785-
struct perf_event_context *ctx = leader->ctx;
3786-
int n = 0, size = 0, ret;
3787-
u64 count, enabled, running;
3788-
u64 values[5];
3784+
struct perf_event *sub;
3785+
int n = 1; /* skip @nr */
37893786

3790-
lockdep_assert_held(&ctx->mutex);
3787+
perf_event_read(leader, true);
3788+
3789+
/*
3790+
* Since we co-schedule groups, {enabled,running} times of siblings
3791+
* will be identical to those of the leader, so we only publish one
3792+
* set.
3793+
*/
3794+
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
3795+
values[n++] += leader->total_time_enabled +
3796+
atomic64_read(&leader->child_total_time_enabled);
3797+
}
37913798

3792-
count = perf_event_read_value(leader, &enabled, &running);
3799+
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
3800+
values[n++] += leader->total_time_running +
3801+
atomic64_read(&leader->child_total_time_running);
3802+
}
37933803

3794-
values[n++] = 1 + leader->nr_siblings;
3795-
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
3796-
values[n++] = enabled;
3797-
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
3798-
values[n++] = running;
3799-
values[n++] = count;
3804+
/*
3805+
* Write {count,id} tuples for every sibling.
3806+
*/
3807+
values[n++] += perf_event_count(leader);
38003808
if (read_format & PERF_FORMAT_ID)
38013809
values[n++] = primary_event_id(leader);
38023810

3803-
size = n * sizeof(u64);
3811+
list_for_each_entry(sub, &leader->sibling_list, group_entry) {
3812+
values[n++] += perf_event_count(sub);
3813+
if (read_format & PERF_FORMAT_ID)
3814+
values[n++] = primary_event_id(sub);
3815+
}
3816+
}
38043817

3805-
if (copy_to_user(buf, values, size))
3806-
return -EFAULT;
3818+
static int perf_read_group(struct perf_event *event,
3819+
u64 read_format, char __user *buf)
3820+
{
3821+
struct perf_event *leader = event->group_leader, *child;
3822+
struct perf_event_context *ctx = leader->ctx;
3823+
int ret = event->read_size;
3824+
u64 *values;
38073825

3808-
ret = size;
3826+
lockdep_assert_held(&ctx->mutex);
38093827

3810-
list_for_each_entry(sub, &leader->sibling_list, group_entry) {
3811-
n = 0;
3828+
values = kzalloc(event->read_size, GFP_KERNEL);
3829+
if (!values)
3830+
return -ENOMEM;
38123831

3813-
values[n++] = perf_event_read_value(sub, &enabled, &running);
3814-
if (read_format & PERF_FORMAT_ID)
3815-
values[n++] = primary_event_id(sub);
3832+
values[0] = 1 + leader->nr_siblings;
3833+
3834+
/*
3835+
* By locking the child_mutex of the leader we effectively
3836+
* lock the child list of all siblings.. XXX explain how.
3837+
*/
3838+
mutex_lock(&leader->child_mutex);
38163839

3817-
size = n * sizeof(u64);
3840+
__perf_read_group_add(leader, read_format, values);
3841+
list_for_each_entry(child, &leader->child_list, child_list)
3842+
__perf_read_group_add(child, read_format, values);
38183843

3819-
if (copy_to_user(buf + ret, values, size)) {
3820-
return -EFAULT;
3821-
}
3844+
mutex_unlock(&leader->child_mutex);
38223845

3823-
ret += size;
3824-
}
3846+
if (copy_to_user(buf, values, event->read_size))
3847+
ret = -EFAULT;
3848+
3849+
kfree(values);
38253850

38263851
return ret;
38273852
}

0 commit comments

Comments
 (0)