Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu: (46 commits) powerpc64: convert to dynamic percpu allocator sparc64: use embedding percpu first chunk allocator percpu: kill lpage first chunk allocator x86,percpu: use embedding for 64bit NUMA and page for 32bit NUMA percpu: update embedding first chunk allocator to handle sparse units percpu: use group information to allocate vmap areas sparsely vmalloc: implement pcpu_get_vm_areas() vmalloc: separate out insert_vmalloc_vm() percpu: add chunk->base_addr percpu: add pcpu_unit_offsets[] percpu: introduce pcpu_alloc_info and pcpu_group_info percpu: move pcpu_lpage_build_unit_map() and pcpul_lpage_dump_cfg() upward percpu: add @align to pcpu_fc_alloc_fn_t percpu: make @dyn_size mandatory for pcpu_setup_first_chunk() percpu: drop @static_size from first chunk allocators percpu: generalize first chunk allocator selection percpu: build first chunk allocators selectively percpu: rename 4k first chunk allocator to page percpu: improve boot messages percpu: fix pcpu_reclaim() locking ... Fix trivial conflict as by Tejun Heo in kernel/sched.c
This commit is contained in:
commit
ada3fa1505
80 changed files with 1912 additions and 1230 deletions
|
@ -10,22 +10,70 @@
|
|||
/*
|
||||
* Base implementations of per-CPU variable declarations and definitions, where
|
||||
* the section in which the variable is to be placed is provided by the
|
||||
* 'section' argument. This may be used to affect the parameters governing the
|
||||
* 'sec' argument. This may be used to affect the parameters governing the
|
||||
* variable's storage.
|
||||
*
|
||||
* NOTE! The sections for the DECLARE and for the DEFINE must match, lest
|
||||
* linkage errors occur due the compiler generating the wrong code to access
|
||||
* that section.
|
||||
*/
|
||||
#define DECLARE_PER_CPU_SECTION(type, name, section) \
|
||||
extern \
|
||||
__attribute__((__section__(PER_CPU_BASE_SECTION section))) \
|
||||
PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name
|
||||
#define __PCPU_ATTRS(sec) \
|
||||
__attribute__((section(PER_CPU_BASE_SECTION sec))) \
|
||||
PER_CPU_ATTRIBUTES
|
||||
|
||||
#define DEFINE_PER_CPU_SECTION(type, name, section) \
|
||||
__attribute__((__section__(PER_CPU_BASE_SECTION section))) \
|
||||
PER_CPU_ATTRIBUTES PER_CPU_DEF_ATTRIBUTES \
|
||||
#define __PCPU_DUMMY_ATTRS \
|
||||
__attribute__((section(".discard"), unused))
|
||||
|
||||
/*
|
||||
* s390 and alpha modules require percpu variables to be defined as
|
||||
* weak to force the compiler to generate GOT based external
|
||||
* references for them. This is necessary because percpu sections
|
||||
* will be located outside of the usually addressable area.
|
||||
*
|
||||
* This definition puts the following two extra restrictions when
|
||||
* defining percpu variables.
|
||||
*
|
||||
* 1. The symbol must be globally unique, even the static ones.
|
||||
* 2. Static percpu variables cannot be defined inside a function.
|
||||
*
|
||||
* Archs which need weak percpu definitions should define
|
||||
* ARCH_NEEDS_WEAK_PER_CPU in asm/percpu.h when necessary.
|
||||
*
|
||||
* To ensure that the generic code observes the above two
|
||||
* restrictions, if CONFIG_DEBUG_FORCE_WEAK_PER_CPU is set weak
|
||||
* definition is used for all cases.
|
||||
*/
|
||||
#if defined(ARCH_NEEDS_WEAK_PER_CPU) || defined(CONFIG_DEBUG_FORCE_WEAK_PER_CPU)
|
||||
/*
|
||||
* __pcpu_scope_* dummy variable is used to enforce scope. It
|
||||
* receives the static modifier when it's used in front of
|
||||
* DEFINE_PER_CPU() and will trigger build failure if
|
||||
* DECLARE_PER_CPU() is used for the same variable.
|
||||
*
|
||||
* __pcpu_unique_* dummy variable is used to enforce symbol uniqueness
|
||||
* such that hidden weak symbol collision, which will cause unrelated
|
||||
* variables to share the same address, can be detected during build.
|
||||
*/
|
||||
#define DECLARE_PER_CPU_SECTION(type, name, sec) \
|
||||
extern __PCPU_DUMMY_ATTRS char __pcpu_scope_##name; \
|
||||
extern __PCPU_ATTRS(sec) __typeof__(type) per_cpu__##name
|
||||
|
||||
#define DEFINE_PER_CPU_SECTION(type, name, sec) \
|
||||
__PCPU_DUMMY_ATTRS char __pcpu_scope_##name; \
|
||||
__PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \
|
||||
__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak \
|
||||
__typeof__(type) per_cpu__##name
|
||||
#else
|
||||
/*
|
||||
* Normal declaration and definition macros.
|
||||
*/
|
||||
#define DECLARE_PER_CPU_SECTION(type, name, sec) \
|
||||
extern __PCPU_ATTRS(sec) __typeof__(type) per_cpu__##name
|
||||
|
||||
#define DEFINE_PER_CPU_SECTION(type, name, sec) \
|
||||
__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES \
|
||||
__typeof__(type) per_cpu__##name
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Variant on the per-CPU variable declaration/definition theme used for
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA
|
||||
#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
|
||||
|
||||
/* minimum unit size, also is the maximum supported allocation size */
|
||||
#define PCPU_MIN_UNIT_SIZE PFN_ALIGN(64 << 10)
|
||||
|
@ -57,19 +57,70 @@
|
|||
#endif
|
||||
|
||||
extern void *pcpu_base_addr;
|
||||
extern const unsigned long *pcpu_unit_offsets;
|
||||
|
||||
typedef struct page * (*pcpu_get_page_fn_t)(unsigned int cpu, int pageno);
|
||||
typedef void (*pcpu_populate_pte_fn_t)(unsigned long addr);
|
||||
struct pcpu_group_info {
|
||||
int nr_units; /* aligned # of units */
|
||||
unsigned long base_offset; /* base address offset */
|
||||
unsigned int *cpu_map; /* unit->cpu map, empty
|
||||
* entries contain NR_CPUS */
|
||||
};
|
||||
|
||||
extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
|
||||
size_t static_size, size_t reserved_size,
|
||||
ssize_t dyn_size, ssize_t unit_size,
|
||||
void *base_addr,
|
||||
pcpu_populate_pte_fn_t populate_pte_fn);
|
||||
struct pcpu_alloc_info {
|
||||
size_t static_size;
|
||||
size_t reserved_size;
|
||||
size_t dyn_size;
|
||||
size_t unit_size;
|
||||
size_t atom_size;
|
||||
size_t alloc_size;
|
||||
size_t __ai_size; /* internal, don't use */
|
||||
int nr_groups; /* 0 if grouping unnecessary */
|
||||
struct pcpu_group_info groups[];
|
||||
};
|
||||
|
||||
extern ssize_t __init pcpu_embed_first_chunk(
|
||||
size_t static_size, size_t reserved_size,
|
||||
ssize_t dyn_size, ssize_t unit_size);
|
||||
enum pcpu_fc {
|
||||
PCPU_FC_AUTO,
|
||||
PCPU_FC_EMBED,
|
||||
PCPU_FC_PAGE,
|
||||
|
||||
PCPU_FC_NR,
|
||||
};
|
||||
extern const char *pcpu_fc_names[PCPU_FC_NR];
|
||||
|
||||
extern enum pcpu_fc pcpu_chosen_fc;
|
||||
|
||||
typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size,
|
||||
size_t align);
|
||||
typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size);
|
||||
typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr);
|
||||
typedef int (pcpu_fc_cpu_distance_fn_t)(unsigned int from, unsigned int to);
|
||||
|
||||
extern struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups,
|
||||
int nr_units);
|
||||
extern void __init pcpu_free_alloc_info(struct pcpu_alloc_info *ai);
|
||||
|
||||
extern struct pcpu_alloc_info * __init pcpu_build_alloc_info(
|
||||
size_t reserved_size, ssize_t dyn_size,
|
||||
size_t atom_size,
|
||||
pcpu_fc_cpu_distance_fn_t cpu_distance_fn);
|
||||
|
||||
extern int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
|
||||
void *base_addr);
|
||||
|
||||
#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
extern int __init pcpu_embed_first_chunk(size_t reserved_size, ssize_t dyn_size,
|
||||
size_t atom_size,
|
||||
pcpu_fc_cpu_distance_fn_t cpu_distance_fn,
|
||||
pcpu_fc_alloc_fn_t alloc_fn,
|
||||
pcpu_fc_free_fn_t free_fn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
extern int __init pcpu_page_first_chunk(size_t reserved_size,
|
||||
pcpu_fc_alloc_fn_t alloc_fn,
|
||||
pcpu_fc_free_fn_t free_fn,
|
||||
pcpu_fc_populate_pte_fn_t populate_pte_fn);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use this to get to a cpu's version of the per-cpu object
|
||||
|
@ -80,7 +131,7 @@ extern ssize_t __init pcpu_embed_first_chunk(
|
|||
|
||||
extern void *__alloc_reserved_percpu(size_t size, size_t align);
|
||||
|
||||
#else /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */
|
||||
#else /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
|
||||
|
||||
struct percpu_data {
|
||||
void *ptrs[1];
|
||||
|
@ -99,11 +150,15 @@ struct percpu_data {
|
|||
(__typeof__(ptr))__p->ptrs[(cpu)]; \
|
||||
})
|
||||
|
||||
#endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */
|
||||
#endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
|
||||
|
||||
extern void *__alloc_percpu(size_t size, size_t align);
|
||||
extern void free_percpu(void *__pdata);
|
||||
|
||||
#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
|
||||
extern void __init setup_per_cpu_areas(void);
|
||||
#endif
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
|
||||
|
@ -124,6 +179,13 @@ static inline void free_percpu(void *p)
|
|||
kfree(p);
|
||||
}
|
||||
|
||||
static inline void __init setup_per_cpu_areas(void) { }
|
||||
|
||||
static inline void *pcpu_lpage_remapped(void *kaddr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type), \
|
||||
|
|
|
@ -115,4 +115,10 @@ extern rwlock_t vmlist_lock;
|
|||
extern struct vm_struct *vmlist;
|
||||
extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
|
||||
|
||||
struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
|
||||
const size_t *sizes, int nr_vms,
|
||||
size_t align, gfp_t gfp_mask);
|
||||
|
||||
void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms);
|
||||
|
||||
#endif /* _LINUX_VMALLOC_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue