Commit 1347e965 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-fixes-for-linus' of...

Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  generic-ipi: use per cpu data for single cpu ipi calls
  cpumask: convert lib/smp_processor_id to new cpumask ops
  signals, debug: fix BUG: using smp_processor_id() in preemptible code in print_fatal_signal()
parents ac56b94f d7240b98
...@@ -909,7 +909,9 @@ static void print_fatal_signal(struct pt_regs *regs, int signr) ...@@ -909,7 +909,9 @@ static void print_fatal_signal(struct pt_regs *regs, int signr)
} }
#endif #endif
printk("\n"); printk("\n");
preempt_disable();
show_regs(regs); show_regs(regs);
preempt_enable();
} }
static int __init setup_print_fatal_signals(char *str) static int __init setup_print_fatal_signals(char *str)
......
...@@ -18,6 +18,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_function_lock); ...@@ -18,6 +18,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_function_lock);
enum { enum {
CSD_FLAG_WAIT = 0x01, CSD_FLAG_WAIT = 0x01,
CSD_FLAG_ALLOC = 0x02, CSD_FLAG_ALLOC = 0x02,
CSD_FLAG_LOCK = 0x04,
}; };
struct call_function_data { struct call_function_data {
...@@ -186,6 +187,9 @@ void generic_smp_call_function_single_interrupt(void) ...@@ -186,6 +187,9 @@ void generic_smp_call_function_single_interrupt(void)
if (data_flags & CSD_FLAG_WAIT) { if (data_flags & CSD_FLAG_WAIT) {
smp_wmb(); smp_wmb();
data->flags &= ~CSD_FLAG_WAIT; data->flags &= ~CSD_FLAG_WAIT;
} else if (data_flags & CSD_FLAG_LOCK) {
smp_wmb();
data->flags &= ~CSD_FLAG_LOCK;
} else if (data_flags & CSD_FLAG_ALLOC) } else if (data_flags & CSD_FLAG_ALLOC)
kfree(data); kfree(data);
} }
...@@ -196,6 +200,8 @@ void generic_smp_call_function_single_interrupt(void) ...@@ -196,6 +200,8 @@ void generic_smp_call_function_single_interrupt(void)
} }
} }
static DEFINE_PER_CPU(struct call_single_data, csd_data);
/* /*
* smp_call_function_single - Run a function on a specific CPU * smp_call_function_single - Run a function on a specific CPU
* @func: The function to run. This must be fast and non-blocking. * @func: The function to run. This must be fast and non-blocking.
...@@ -224,14 +230,38 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, ...@@ -224,14 +230,38 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
func(info); func(info);
local_irq_restore(flags); local_irq_restore(flags);
} else if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) { } else if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {
struct call_single_data *data = NULL; struct call_single_data *data;
if (!wait) { if (!wait) {
/*
* We are calling a function on a single CPU
* and we are not going to wait for it to finish.
* We first try to allocate the data, but if we
* fail, we fall back to use a per cpu data to pass
* the information to that CPU. Since all callers
* of this code will use the same data, we must
* synchronize the callers to prevent a new caller
* from corrupting the data before the callee
* can access it.
*
* The CSD_FLAG_LOCK is used to let us know when
* the IPI handler is done with the data.
* The first caller will set it, and the callee
* will clear it. The next caller must wait for
* it to clear before we set it again. This
* will make sure the callee is done with the
* data before a new caller will use it.
*/
data = kmalloc(sizeof(*data), GFP_ATOMIC); data = kmalloc(sizeof(*data), GFP_ATOMIC);
if (data) if (data)
data->flags = CSD_FLAG_ALLOC; data->flags = CSD_FLAG_ALLOC;
} else {
if (!data) { data = &per_cpu(csd_data, me);
while (data->flags & CSD_FLAG_LOCK)
cpu_relax();
data->flags = CSD_FLAG_LOCK;
}
} else {
data = &d; data = &d;
data->flags = CSD_FLAG_WAIT; data->flags = CSD_FLAG_WAIT;
} }
......
...@@ -22,7 +22,7 @@ notrace unsigned int debug_smp_processor_id(void) ...@@ -22,7 +22,7 @@ notrace unsigned int debug_smp_processor_id(void)
* Kernel threads bound to a single CPU can safely use * Kernel threads bound to a single CPU can safely use
* smp_processor_id(): * smp_processor_id():
*/ */
if (cpus_equal(current->cpus_allowed, cpumask_of_cpu(this_cpu))) if (cpumask_equal(&current->cpus_allowed, cpumask_of(this_cpu)))
goto out; goto out;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment