Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 257019
b: refs/heads/master
c: 2c29ef0
h: refs/heads/master
i:
  257017: 31d5201
  257015: d57b0f6
v: v3
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed May 28, 2011
1 parent 445871d commit ee20f3c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 46 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 04dc2dbbfe1c6f81b996d4dab255da75f9efbb4a
refs/heads/master: 2c29ef0fef8aaff1f91263fc75c749d659da6972
80 changes: 35 additions & 45 deletions trunk/kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,8 +1469,12 @@ static void add_event_to_ctx(struct perf_event *event,
event->tstamp_stopped = tstamp;
}

static void perf_event_context_sched_in(struct perf_event_context *ctx,
struct task_struct *tsk);
static void task_ctx_sched_out(struct perf_event_context *ctx);
static void
ctx_sched_in(struct perf_event_context *ctx,
struct perf_cpu_context *cpuctx,
enum event_type_t event_type,
struct task_struct *task);

/*
* Cross CPU call to install and enable a performance event
Expand All @@ -1481,20 +1485,31 @@ static int __perf_install_in_context(void *info)
{
struct perf_event *event = info;
struct perf_event_context *ctx = event->ctx;
struct perf_event *leader = event->group_leader;
struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
int err;
struct perf_event_context *task_ctx = cpuctx->task_ctx;
struct task_struct *task = current;

perf_ctx_lock(cpuctx, cpuctx->task_ctx);
perf_pmu_disable(cpuctx->ctx.pmu);

/*
* In case we're installing a new context to an already running task,
* could also happen before perf_event_task_sched_in() on architectures
* which do context switches with IRQs enabled.
* If there was an active task_ctx schedule it out.
*/
if (ctx->task && !cpuctx->task_ctx)
perf_event_context_sched_in(ctx, ctx->task);
if (task_ctx) {
task_ctx_sched_out(task_ctx);
/*
* If the context we're installing events in is not the
* active task_ctx, flip them.
*/
if (ctx->task && task_ctx != ctx) {
raw_spin_unlock(&cpuctx->ctx.lock);
raw_spin_lock(&ctx->lock);
cpuctx->task_ctx = task_ctx = ctx;
}
task = task_ctx->task;
}
cpu_ctx_sched_out(cpuctx, EVENT_ALL);

raw_spin_lock(&ctx->lock);
ctx->is_active = 1;
update_context_time(ctx);
/*
* update cgrp time only if current cgrp
Expand All @@ -1505,43 +1520,18 @@ static int __perf_install_in_context(void *info)

add_event_to_ctx(event, ctx);

if (!event_filter_match(event))
goto unlock;

/*
* Don't put the event on if it is disabled or if
* it is in a group and the group isn't on.
*/
if (event->state != PERF_EVENT_STATE_INACTIVE ||
(leader != event && leader->state != PERF_EVENT_STATE_ACTIVE))
goto unlock;

/*
* An exclusive event can't go on if there are already active
* hardware events, and no hardware event can go on if there
* is already an exclusive event on.
* Schedule everything back in
*/
if (!group_can_go_on(event, cpuctx, 1))
err = -EEXIST;
else
err = event_sched_in(event, cpuctx, ctx);

if (err) {
/*
* This event couldn't go on. If it is in a group
* then we have to pull the whole group off.
* If the event group is pinned then put it in error state.
*/
if (leader != event)
group_sched_out(leader, cpuctx, ctx);
if (leader->attr.pinned) {
update_group_times(leader);
leader->state = PERF_EVENT_STATE_ERROR;
}
}
cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task);
if (task_ctx)
ctx_sched_in(task_ctx, cpuctx, EVENT_PINNED, task);
cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task);
if (task_ctx)
ctx_sched_in(task_ctx, cpuctx, EVENT_FLEXIBLE, task);

unlock:
raw_spin_unlock(&ctx->lock);
perf_pmu_enable(cpuctx->ctx.pmu);
perf_ctx_unlock(cpuctx, task_ctx);

return 0;
}
Expand Down

0 comments on commit ee20f3c

Please sign in to comment.