static void perf_remove_from_context(struct perf_event *event)
{
	struct perf_event_context *ctx = event->ctx;
	struct task_struct *task = ctx->task;

	lockdep_assert_held(&ctx->mutex);

	if (!task) {
		/*
		 * Per cpu events are removed via an smp call and
		 * the removal is always successful.
		 */
		cpu_function_call(event->cpu, __perf_remove_from_context, event);
		return;
	}

retry:
	if (!task_function_call(task, __perf_remove_from_context, event))
		return;

	raw_spin_lock_irq(&ctx->lock);
	/*
	 * If we failed to find a running task, but find the context active now
	 * that we've acquired the ctx->lock, retry.
	 */
	if (ctx->is_active) {
		raw_spin_unlock_irq(&ctx->lock);
		goto retry;
	}

	/*
	 * Since the task isn't running, its safe to remove the event, us
	 * holding the ctx->lock ensures the task won't get scheduled in.
	 */
	list_del_event(event, ctx);
	raw_spin_unlock_irq(&ctx->lock);
}
static void perf_remove_from_context(struct perf_event *event)
{
	struct perf_event_context *ctx = event->ctx;
	struct task_struct *task = ctx->task;

	lockdep_assert_held(&ctx->mutex);

	if (!task) {
		 
		cpu_function_call(event->cpu, __perf_remove_from_context, event);
		return;
	}

retry:
	if (!task_function_call(task, __perf_remove_from_context, event))
		return;

	raw_spin_lock_irq(&ctx->lock);
	 
	if (ctx->is_active) {
		raw_spin_unlock_irq(&ctx->lock);
		goto retry;
	}

	 
	list_del_event(event, ctx);
	raw_spin_unlock_irq(&ctx->lock);
}