cpumask: Fix invalid uniprocessor mask assumption
On uniprocessor builds, any CPU mask is assumed to contain exactly one CPU (cpu0). This assumption ignores the existence of empty masks, resulting in incorrect behaviour. cpumask_first_zero(), cpumask_next_zero(), and for_each_cpu_not() don't provide behaviour matching the assumption that a UP mask is always "1", and instead provide behaviour matching the empty mask. Drop the incorrectly optimised code and use the generic implementations in all cases. Link: https://lkml.kernel.org/r/86bf3f005abba2d92120ddd0809235cab4f759a6.1656777646.git.sander@svanheule.net Signed-off-by: Sander Vanheule <sander@svanheule.net> Suggested-by: Yury Norov <yury.norov@gmail.com> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Marco Elver <elver@google.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Valentin Schneider <vschneid@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Родитель
4f09903078
Коммит
b81dce77ce
|
@ -116,85 +116,6 @@ static __always_inline unsigned int cpumask_check(unsigned int cpu)
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NR_CPUS == 1
|
|
||||||
/* Uniprocessor. Assume all masks are "1". */
|
|
||||||
static inline unsigned int cpumask_first(const struct cpumask *srcp)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_first_zero(const struct cpumask *srcp)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_first_and(const struct cpumask *srcp1,
|
|
||||||
const struct cpumask *srcp2)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_last(const struct cpumask *srcp)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Valid inputs for n are -1 and 0. */
|
|
||||||
static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
|
|
||||||
{
|
|
||||||
return n+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp)
|
|
||||||
{
|
|
||||||
return n+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_next_and(int n,
|
|
||||||
const struct cpumask *srcp,
|
|
||||||
const struct cpumask *andp)
|
|
||||||
{
|
|
||||||
return n+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_next_wrap(int n, const struct cpumask *mask,
|
|
||||||
int start, bool wrap)
|
|
||||||
{
|
|
||||||
/* cpu0 unless stop condition, wrap and at cpu0, then nr_cpumask_bits */
|
|
||||||
return (wrap && n == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cpu must be a valid cpu, ie 0, so there's no other choice. */
|
|
||||||
static inline unsigned int cpumask_any_but(const struct cpumask *mask,
|
|
||||||
unsigned int cpu)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int cpumask_local_spread(unsigned int i, int node)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int cpumask_any_and_distribute(const struct cpumask *src1p,
|
|
||||||
const struct cpumask *src2p) {
|
|
||||||
return cpumask_first_and(src1p, src2p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int cpumask_any_distribute(const struct cpumask *srcp)
|
|
||||||
{
|
|
||||||
return cpumask_first(srcp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define for_each_cpu(cpu, mask) \
|
|
||||||
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
|
|
||||||
#define for_each_cpu_not(cpu, mask) \
|
|
||||||
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
|
|
||||||
#define for_each_cpu_wrap(cpu, mask, start) \
|
|
||||||
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)(start))
|
|
||||||
#define for_each_cpu_and(cpu, mask1, mask2) \
|
|
||||||
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask1, (void)mask2)
|
|
||||||
#else
|
|
||||||
/**
|
/**
|
||||||
* cpumask_first - get the first cpu in a cpumask
|
* cpumask_first - get the first cpu in a cpumask
|
||||||
* @srcp: the cpumask pointer
|
* @srcp: the cpumask pointer
|
||||||
|
@ -260,10 +181,29 @@ static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp)
|
||||||
|
|
||||||
int __pure cpumask_next_and(int n, const struct cpumask *, const struct cpumask *);
|
int __pure cpumask_next_and(int n, const struct cpumask *, const struct cpumask *);
|
||||||
int __pure cpumask_any_but(const struct cpumask *mask, unsigned int cpu);
|
int __pure cpumask_any_but(const struct cpumask *mask, unsigned int cpu);
|
||||||
|
|
||||||
|
#if NR_CPUS == 1
|
||||||
|
/* Uniprocessor: there is only one valid CPU */
|
||||||
|
static inline unsigned int cpumask_local_spread(unsigned int i, int node)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cpumask_any_and_distribute(const struct cpumask *src1p,
|
||||||
|
const struct cpumask *src2p) {
|
||||||
|
return cpumask_first_and(src1p, src2p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cpumask_any_distribute(const struct cpumask *srcp)
|
||||||
|
{
|
||||||
|
return cpumask_first(srcp);
|
||||||
|
}
|
||||||
|
#else
|
||||||
unsigned int cpumask_local_spread(unsigned int i, int node);
|
unsigned int cpumask_local_spread(unsigned int i, int node);
|
||||||
int cpumask_any_and_distribute(const struct cpumask *src1p,
|
int cpumask_any_and_distribute(const struct cpumask *src1p,
|
||||||
const struct cpumask *src2p);
|
const struct cpumask *src2p);
|
||||||
int cpumask_any_distribute(const struct cpumask *srcp);
|
int cpumask_any_distribute(const struct cpumask *srcp);
|
||||||
|
#endif /* NR_CPUS */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* for_each_cpu - iterate over every cpu in a mask
|
* for_each_cpu - iterate over every cpu in a mask
|
||||||
|
@ -324,7 +264,6 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool
|
||||||
for ((cpu) = -1; \
|
for ((cpu) = -1; \
|
||||||
(cpu) = cpumask_next_and((cpu), (mask1), (mask2)), \
|
(cpu) = cpumask_next_and((cpu), (mask1), (mask2)), \
|
||||||
(cpu) < nr_cpu_ids;)
|
(cpu) < nr_cpu_ids;)
|
||||||
#endif /* SMP */
|
|
||||||
|
|
||||||
#define CPU_BITS_NONE \
|
#define CPU_BITS_NONE \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -34,10 +34,9 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
|
||||||
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
|
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
|
||||||
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
|
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
|
||||||
nmi_backtrace.o nodemask.o win_minmax.o memcat_p.o \
|
nmi_backtrace.o nodemask.o win_minmax.o memcat_p.o \
|
||||||
buildid.o
|
buildid.o cpumask.o
|
||||||
|
|
||||||
lib-$(CONFIG_PRINTK) += dump_stack.o
|
lib-$(CONFIG_PRINTK) += dump_stack.o
|
||||||
lib-$(CONFIG_SMP) += cpumask.o
|
|
||||||
|
|
||||||
lib-y += kobject.o klist.o
|
lib-y += kobject.o klist.o
|
||||||
obj-y += lockref.o
|
obj-y += lockref.o
|
||||||
|
|
|
@ -192,6 +192,7 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if NR_CPUS > 1
|
||||||
/**
|
/**
|
||||||
* cpumask_local_spread - select the i'th cpu with local numa cpu's first
|
* cpumask_local_spread - select the i'th cpu with local numa cpu's first
|
||||||
* @i: index number
|
* @i: index number
|
||||||
|
@ -279,3 +280,4 @@ int cpumask_any_distribute(const struct cpumask *srcp)
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cpumask_any_distribute);
|
EXPORT_SYMBOL(cpumask_any_distribute);
|
||||||
|
#endif /* NR_CPUS */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче