Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eaa70773 authored by Stephane Eranian's avatar Stephane Eranian Committed by Linus Torvalds
Browse files

[PATCH] i386: add smp_call_function_single



Continiung the series of small patches necessary for the perfmon subsystem,
here is a patch that adds support for the smp_call_function_single()
function for i386.  It exists for almost all other architectures but i386.
The perfmon subsystem needs it in one case to free some state on a
designated remote CPU.

Signed-off-by: default avatarStephane Eranian <eranian@hpl.hp.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 27d26666
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
@@ -634,3 +634,69 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
	}
}

/*
 * this function sends a 'generic call function' IPI to one other CPU
 * in the system.
 *
 * cpu is a standard Linux logical CPU number.
 */
static void
__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
				int nonatomic, int wait)
{
	struct call_data_struct data;
	int cpus = 1;

	data.func = func;
	data.info = info;
	atomic_set(&data.started, 0);
	data.wait = wait;
	if (wait)
		atomic_set(&data.finished, 0);

	call_data = &data;
	wmb();
	/* Send a message to all other CPUs and wait for them to respond */
	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);

	/* Wait for response */
	while (atomic_read(&data.started) != cpus)
		cpu_relax();

	if (!wait)
		return;

	while (atomic_read(&data.finished) != cpus)
		cpu_relax();
}

/*
 * smp_call_function_single - Run a function on another CPU
 * @func: The function to run. This must be fast and non-blocking.
 * @info: An arbitrary pointer to pass to the function.
 * @nonatomic: Currently unused.
 * @wait: If true, wait until function has completed on other CPUs.
 *
 * Retrurns 0 on success, else a negative status code.
 *
 * Does not return until the remote CPU is nearly ready to execute <func>
 * or is or has executed.
 */

int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
	int nonatomic, int wait)
{
	/* prevent preemption and reschedule on another processor */
	int me = get_cpu();
	if (cpu == me) {
		WARN_ON(1);
		put_cpu();
		return -EBUSY;
	}
	spin_lock_bh(&call_lock);
	__smp_call_function_single(cpu, func, info, nonatomic, wait);
	spin_unlock_bh(&call_lock);
	put_cpu();
	return 0;
}
EXPORT_SYMBOL(smp_call_function_single);