per-cpu support inside modules (minimal)
PATCH 1/1 per-cpu support inside modules (minimal)
OK, this does the *minimum* required to support DEFINE_PER_CPU inside modules. If we decide to change kmalloc_percpu later, great, we can turf this out.
Basically, overallocates the amount of per-cpu data at boot to at least PERCPU_ENOUGH_ROOM if CONFIG_MODULES=y (arch-specific by default 16k: I have only 5700 bytes of percpu data in my kernel here, so makes sense), and a special allocator in module.c dishes it out.
Comments welcome!
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
Name: per-cpu support inside modules
Author: Rusty Russell
Status: Tested on 2.5.69-bk14
D: This adds percpu support for modules.
include/asm-generic/percpu.h +8 -6
@@ -4,26 +4,28 @@#define __GENERIC_PER_CPU#ifdef CONFIG_SMP -extern unsigned long __per_cpu_offset[NR_CPUS ];/* Separate out the type, so (int[3], foo) works. */ -#ifndef MODULE #define DEFINE_PER_CPU (type, name) \ __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu -#endif /* var is in discarded region: offset to particular copy we want */ #define per_cpu (var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))#define __get_cpu_var (var) per_cpu(var, smp_processor_id()) +static inline void percpu_modcopy (void *pcpudst,const void *src, +unsigned long size) +{ +unsigned int i; +for (i =0 ; i <NR_CPUS ; i++) +if (cpu_possible (i)) +memcpy (pcpudst + __per_cpu_offset[i], src, size); +}#else /* ! SMP */ -/* Can't define per-cpu variables in modules. Sorry --RR */ -#ifndef MODULE #define DEFINE_PER_CPU (type, name) \ __typeof__(type) name##__per_cpu -#endif #define per_cpu (var, cpu) ((void)cpu, var##__per_cpu)#define __get_cpu_var (var) var##__per_cpu
include/asm-ia64/percpu.h +9 -2
@@ -19,15 +19,22 @@extern unsigned long __per_cpu_offset[NR_CPUS ]; -#ifndef MODULE #define DEFINE_PER_CPU (type, name) \ __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu -#endif #define DECLARE_PER_CPU (type, name) extern __typeof__(type) name##__per_cpu#define __get_cpu_var (var) (var##__per_cpu)#ifdef CONFIG_SMP # define per_cpu (var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu])) + +static inline void percpu_modcopy (void *pcpudst,const void *src, +unsigned long size) +{ +unsigned int i; +for (i =0 ; i <NR_CPUS ; i++) +if (cpu_possible (i)) +memcpy (pcpudst + __per_cpu_offset[i], src, size); +}#else # define per_cpu (var, cpu) ((void)cpu, __get_cpu_var(var))#endif
include/linux/module.h +3 -0
@@ -247,6 +247,9 @@ struct modulechar *strtab;#endif +/* Per-cpu data. */ +void *percpu; +/* The command line arguments (may be mangled). People like keeping pointers to this stuff */ char *args;
include/linux/percpu.h +8 -1
@@ -1,9 +1,16 @@#ifndef __LINUX_PERCPU_H#define __LINUX_PERCPU_H#include <linux/spinlock.h> /* For preempt_disable() */ -#include <linux/slab.h> /* For kmalloc_percpu() */ +#include <linux/slab.h> /* For kmalloc() */ +#include <linux/smp.h> +#include <linux/string.h> #include <asm/percpu.h> +/* Enough to cover all DEFINE_PER_CPUs in kernel, including modules. */ +#ifndef PERCPU_ENOUGH_ROOM +#define PERCPU_ENOUGH_ROOM 16384 +#endif +/* Must be an lvalue. */ #define get_cpu_var (var) (*({ preempt_disable(); &__get_cpu_var(var); }))#define put_cpu_var (var) preempt_enable()
init/main.c +5 -3
@@ -318,14 +318,16 @@ static void __init setup_per_cpu_areas(v/* Copy section for each CPU (we discard the original) */ size =ALIGN (__per_cpu_end - __per_cpu_start,SMP_CACHE_BYTES ); -if (!size) -return ; +#ifdef CONFIG_MODULES +if (size <PERCPU_ENOUGH_ROOM ) + size =PERCPU_ENOUGH_ROOM ; +#endif ptr =alloc_bootmem (size *NR_CPUS );for (i =0 ; i <NR_CPUS ; i++, ptr += size) { __per_cpu_offset[i] = ptr - __per_cpu_start; -memcpy (ptr, __per_cpu_start, size); +memcpy (ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); } }#endif /* !__GENERIC_PER_CPU */
kernel/module.c +188 -8
271 lines not on this page · raw message
I'll give this a run on the ppc64 tomorrow.
Quoted 7 lines · Rusty Russell
+static inline unsigned int abs(int val)
+{
+ if (val < 0)
+ return -val;
+ return val;
+}
Several architectures define their own abs() in asm/system.h which return signed int.
In message <[email protected]> you write:
Quoted 9 lines
Quoted 6 lines
+static inline unsigned int abs(int val)
+{
+ if (val < 0)
+ return -val;
+ return val;
+}Several architectures define their own
abs()inasm/system.hwhich return signed int.
Hmm, it's actually declated that way in linux/kernel.h, too:
extern int abs(int);
But AFAICT it's never actually defined.
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
Rusty> OK, this does the *minimum* required to support Rusty> DEFINE_PER_CPU inside modules. If we decide to change Rusty> kmalloc_percpu later, great, we can turf this out.
Rusty> Basically, overallocates the amount of per-cpu data at boot Rusty> to at least PERCPU_ENOUGH_ROOM if CONFIG_MODULES=y Rusty> (arch-specific by default 16k: I have only 5700 bytes of Rusty> percpu data in my kernel here, so makes sense), and a special Rusty> allocator in module.c dishes it out.
Rusty> Comments welcome!
Looks good to me. For ia64, I guess I'll want to add a
#define PERCPU_ENOUGH_ROOM PERCPU_PAGE_SIZE
somewhere, but that doesn't sound so hard. ;-)
Thanks!
--david