Add generic helpers for arch IPI function calls

This adds kernel/smp.c which contains helpers for IPI function calls. In
addition to supporting the existing smp_call_function() in a more efficient
manner, it also adds a more scalable variant called smp_call_function_single()
for calling a given function on a single CPU only.

The core of this is based on the x86-64 patch from Nick Piggin, lots of
changes since then. "Alan D. Brunelle" <Alan.Brunelle@hp.com> has
contributed lots of fixes and suggestions as well. Also thanks to
Paul E. McKenney <paulmck@linux.vnet.ibm.com> for reviewing RCU usage
and getting rid of the data allocation fallback deadlock.

Acked-by: Ingo Molnar <mingo@elte.hu>
Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
Jens Axboe
2008-06-26 11:21:34 +02:00
parent 543cf4cb3f
commit 3d44223327
6 changed files with 428 additions and 7 deletions

View File

@ -7,9 +7,19 @@
*/
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/cpumask.h>
extern void cpu_idle(void);
struct call_single_data {
struct list_head list;
void (*func) (void *info);
void *info;
unsigned int flags;
};
#ifdef CONFIG_SMP
#include <linux/preempt.h>
@ -53,9 +63,28 @@ extern void smp_cpus_done(unsigned int max_cpus);
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int retry, int wait);
int smp_call_function_mask(cpumask_t mask, void(*func)(void *info), void *info,
int wait);
int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
int retry, int wait);
void __smp_call_function_single(int cpuid, struct call_single_data *data);
/*
* Generic and arch helpers
*/
#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
void generic_smp_call_function_single_interrupt(void);
void generic_smp_call_function_interrupt(void);
void init_call_single_data(void);
void ipi_call_lock(void);
void ipi_call_unlock(void);
void ipi_call_lock_irq(void);
void ipi_call_unlock_irq(void);
#else
static inline void init_call_single_data(void)
{
}
#endif
/*
* Call a function on all processors
@ -112,7 +141,9 @@ static inline void smp_send_reschedule(int cpu) { }
})
#define smp_call_function_mask(mask, func, info, wait) \
(up_smp_call_function(func, info))
static inline void init_call_single_data(void)
{
}
#endif /* !SMP */
/*