Skip to content

Commit

Permalink
Add generic helpers for arch IPI function calls
Browse files Browse the repository at this point in the history
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" <[email protected]> has
contributed lots of fixes and suggestions as well. Also thanks to
Paul E. McKenney <[email protected]> for reviewing RCU usage
and getting rid of the data allocation fallback deadlock.

Acked-by: Ingo Molnar <[email protected]>
Reviewed-by: Paul E. McKenney <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
Jens Axboe committed Jun 26, 2008
1 parent 543cf4c commit 3d44223
Show file tree
Hide file tree
Showing 6 changed files with 428 additions and 7 deletions.
3 changes: 3 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ config HAVE_KRETPROBES

config HAVE_DMA_ATTRS
def_bool n

config USE_GENERIC_SMP_HELPERS
def_bool n
11 changes: 6 additions & 5 deletions arch/sparc64/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,9 @@ extern unsigned long xcall_call_function;
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
static int smp_call_function_mask(void (*func)(void *info), void *info,
int nonatomic, int wait, cpumask_t mask)
static int sparc64_smp_call_function_mask(void (*func)(void *info), void *info,
int nonatomic, int wait,
cpumask_t mask)
{
struct call_data_struct data;
int cpus;
Expand Down Expand Up @@ -855,8 +856,8 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
int smp_call_function(void (*func)(void *info), void *info,
int nonatomic, int wait)
{
return smp_call_function_mask(func, info, nonatomic, wait,
cpu_online_map);
return sparc64_smp_call_function_mask(func, info, nonatomic, wait,
cpu_online_map);
}

void smp_call_function_client(int irq, struct pt_regs *regs)
Expand Down Expand Up @@ -893,7 +894,7 @@ static void tsb_sync(void *info)

void smp_tsb_sync(struct mm_struct *mm)
{
smp_call_function_mask(tsb_sync, mm, 0, 1, mm->cpu_vm_mask);
sparc64_smp_call_function_mask(tsb_sync, mm, 0, 1, mm->cpu_vm_mask);
}

extern unsigned long xcall_flush_tlb_mm;
Expand Down
35 changes: 33 additions & 2 deletions include/linux/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */

/*
Expand Down
2 changes: 2 additions & 0 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/kernel_stat.h>
#include <linux/start_kernel.h>
#include <linux/security.h>
#include <linux/smp.h>
#include <linux/workqueue.h>
#include <linux/profile.h>
#include <linux/rcupdate.h>
Expand Down Expand Up @@ -779,6 +780,7 @@ static void __init do_pre_smp_initcalls(void)
{
extern int spawn_ksoftirqd(void);

init_call_single_data();
migration_init();
spawn_ksoftirqd();
if (!nosoftlockup)
Expand Down
1 change: 1 addition & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o spinlock.o
obj-$(CONFIG_USE_GENERIC_SMP_HELPERS) += smp.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
Expand Down
Loading

0 comments on commit 3d44223

Please sign in to comment.