aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Eranian <eranian@hpl.hp.com>2006-09-26 02:32:32 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 11:48:56 -0400
commiteaa70773e750cc09d60938bceacd028bc76b8e3a (patch)
treec88635294b3e26059e25a0dce573bfb8c6ec14e3
parent27d26666fc495166036f4ee2208df25ae7f89ab8 (diff)
[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: Stephane Eranian <eranian@hpl.hp.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/smp.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index c10789d7a9d3..304243ed7a30 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -634,3 +634,69 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
634 } 634 }
635} 635}
636 636
637/*
638 * this function sends a 'generic call function' IPI to one other CPU
639 * in the system.
640 *
641 * cpu is a standard Linux logical CPU number.
642 */
643static void
644__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
645 int nonatomic, int wait)
646{
647 struct call_data_struct data;
648 int cpus = 1;
649
650 data.func = func;
651 data.info = info;
652 atomic_set(&data.started, 0);
653 data.wait = wait;
654 if (wait)
655 atomic_set(&data.finished, 0);
656
657 call_data = &data;
658 wmb();
659 /* Send a message to all other CPUs and wait for them to respond */
660 send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
661
662 /* Wait for response */
663 while (atomic_read(&data.started) != cpus)
664 cpu_relax();
665
666 if (!wait)
667 return;
668
669 while (atomic_read(&data.finished) != cpus)
670 cpu_relax();
671}
672
673/*
674 * smp_call_function_single - Run a function on another CPU
675 * @func: The function to run. This must be fast and non-blocking.
676 * @info: An arbitrary pointer to pass to the function.
677 * @nonatomic: Currently unused.
678 * @wait: If true, wait until function has completed on other CPUs.
679 *
680 * Retrurns 0 on success, else a negative status code.
681 *
682 * Does not return until the remote CPU is nearly ready to execute <func>
683 * or is or has executed.
684 */
685
686int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
687 int nonatomic, int wait)
688{
689 /* prevent preemption and reschedule on another processor */
690 int me = get_cpu();
691 if (cpu == me) {
692 WARN_ON(1);
693 put_cpu();
694 return -EBUSY;
695 }
696 spin_lock_bh(&call_lock);
697 __smp_call_function_single(cpu, func, info, nonatomic, wait);
698 spin_unlock_bh(&call_lock);
699 put_cpu();
700 return 0;
701}
702EXPORT_SYMBOL(smp_call_function_single);