aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2009-12-08 22:29:44 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-09 03:56:27 -0500
commitb93f7978ad6b46133e9453b90ccc057dc2429e75 (patch)
treef3420ebd5fa80ddb1a4c3e302a64861146104385 /kernel
parentaa5452d70c0d559310598b243b8b1033c10056e7 (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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/perf_event.c37
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 */
5084int perf_event_init_task(struct task_struct *child) 5084int 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
5179exit:
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);