diff options
author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2009-12-08 22:29:44 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-09 03:56:27 -0500 |
commit | b93f7978ad6b46133e9453b90ccc057dc2429e75 (patch) | |
tree | f3420ebd5fa80ddb1a4c3e302a64861146104385 | |
parent | aa5452d70c0d559310598b243b8b1033c10056e7 (diff) |
perf_event: Allocate children's perf_event_ctxp at the right time
In current code, children task will allocate memory for
'child->perf_event_ctxp' if the parent is counted, we can
do it only if the parent allowed children inherit it.
It can save memory and reduce overhead.
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Reviewed-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <4B1F19A8.5040805@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | kernel/perf_event.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 2b06c45bfba9..77641ae6b23f 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -5083,7 +5083,7 @@ again: | |||
5083 | */ | 5083 | */ |
5084 | int perf_event_init_task(struct task_struct *child) | 5084 | int perf_event_init_task(struct task_struct *child) |
5085 | { | 5085 | { |
5086 | struct perf_event_context *child_ctx, *parent_ctx; | 5086 | struct perf_event_context *child_ctx = NULL, *parent_ctx; |
5087 | struct perf_event_context *cloned_ctx; | 5087 | struct perf_event_context *cloned_ctx; |
5088 | struct perf_event *event; | 5088 | struct perf_event *event; |
5089 | struct task_struct *parent = current; | 5089 | struct task_struct *parent = current; |
@@ -5099,20 +5099,6 @@ int perf_event_init_task(struct task_struct *child) | |||
5099 | return 0; | 5099 | return 0; |
5100 | 5100 | ||
5101 | /* | 5101 | /* |
5102 | * This is executed from the parent task context, so inherit | ||
5103 | * events that have been marked for cloning. | ||
5104 | * First allocate and initialize a context for the child. | ||
5105 | */ | ||
5106 | |||
5107 | child_ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL); | ||
5108 | if (!child_ctx) | ||
5109 | return -ENOMEM; | ||
5110 | |||
5111 | __perf_event_init_context(child_ctx, child); | ||
5112 | child->perf_event_ctxp = child_ctx; | ||
5113 | get_task_struct(child); | ||
5114 | |||
5115 | /* | ||
5116 | * If the parent's context is a clone, pin it so it won't get | 5102 | * If the parent's context is a clone, pin it so it won't get |
5117 | * swapped under us. | 5103 | * swapped under us. |
5118 | */ | 5104 | */ |
@@ -5142,6 +5128,26 @@ int perf_event_init_task(struct task_struct *child) | |||
5142 | continue; | 5128 | continue; |
5143 | } | 5129 | } |
5144 | 5130 | ||
5131 | if (!child->perf_event_ctxp) { | ||
5132 | /* | ||
5133 | * This is executed from the parent task context, so | ||
5134 | * inherit events that have been marked for cloning. | ||
5135 | * First allocate and initialize a context for the | ||
5136 | * child. | ||
5137 | */ | ||
5138 | |||
5139 | child_ctx = kzalloc(sizeof(struct perf_event_context), | ||
5140 | GFP_KERNEL); | ||
5141 | if (!child_ctx) { | ||
5142 | ret = -ENOMEM; | ||
5143 | goto exit; | ||
5144 | } | ||
5145 | |||
5146 | __perf_event_init_context(child_ctx, child); | ||
5147 | child->perf_event_ctxp = child_ctx; | ||
5148 | get_task_struct(child); | ||
5149 | } | ||
5150 | |||
5145 | ret = inherit_group(event, parent, parent_ctx, | 5151 | ret = inherit_group(event, parent, parent_ctx, |
5146 | child, child_ctx); | 5152 | child, child_ctx); |
5147 | if (ret) { | 5153 | if (ret) { |
@@ -5170,6 +5176,7 @@ int perf_event_init_task(struct task_struct *child) | |||
5170 | get_ctx(child_ctx->parent_ctx); | 5176 | get_ctx(child_ctx->parent_ctx); |
5171 | } | 5177 | } |
5172 | 5178 | ||
5179 | exit: | ||
5173 | mutex_unlock(&parent_ctx->mutex); | 5180 | mutex_unlock(&parent_ctx->mutex); |
5174 | 5181 | ||
5175 | perf_unpin_context(parent_ctx); | 5182 | perf_unpin_context(parent_ctx); |