* [PATCH 1/3] Per-cpu UP unification
@ 2003-05-20 1:22 Rusty Russell
2003-05-20 10:53 ` Andrew Morton
0 siblings, 1 reply; 3+ messages in thread
From: Rusty Russell @ 2003-05-20 1:22 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, David Mosberger-Tang, Dipankar Sarma
[ Untested on ia64, but fairly trivial if I've broken something ].
Name: Unification of per-cpu headers for non-SMP
Author: Rusty Russell
Status: Trivial
D: Move non-SMP per-cpu operations from asm-*/percpu.h to
D: linux/percpu.h. There is no reason why archs would want to have
D: their own versions of non-SMP per-cpu operations, and making each
D: arch override them is just silly.
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .14436-linux-2.5.69-bk13/include/asm-generic/percpu.h .14436-linux-2.5.69-bk13.updated/include/asm-generic/percpu.h
--- .14436-linux-2.5.69-bk13/include/asm-generic/percpu.h 2003-01-02 12:32:47.000000000 +1100
+++ .14436-linux-2.5.69-bk13.updated/include/asm-generic/percpu.h 2003-05-19 15:08:28.000000000 +1000
@@ -17,22 +17,6 @@ extern unsigned long __per_cpu_offset[NR
#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())
-#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
-
#endif /* SMP */
-#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu
-
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
-
#endif /* _ASM_GENERIC_PERCPU_H_ */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .14436-linux-2.5.69-bk13/include/asm-ia64/percpu.h .14436-linux-2.5.69-bk13.updated/include/asm-ia64/percpu.h
--- .14436-linux-2.5.69-bk13/include/asm-ia64/percpu.h 2003-05-19 10:53:49.000000000 +1000
+++ .14436-linux-2.5.69-bk13.updated/include/asm-ia64/percpu.h 2003-05-19 15:08:39.000000000 +1000
@@ -17,23 +17,17 @@
#include <linux/threads.h>
+#ifdef CONFIG_SMP
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]))
-#else
-# define per_cpu(var, cpu) ((void)cpu, __get_cpu_var(var))
-#endif
-
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
+#define per_cpu(var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))
+#endif /* CONFIG_SMP */
extern void setup_per_cpu_areas (void);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .14436-linux-2.5.69-bk13/include/linux/percpu.h .14436-linux-2.5.69-bk13.updated/include/linux/percpu.h
--- .14436-linux-2.5.69-bk13/include/linux/percpu.h 2003-02-07 19:20:01.000000000 +1100
+++ .14436-linux-2.5.69-bk13.updated/include/linux/percpu.h 2003-05-19 15:08:28.000000000 +1000
@@ -44,6 +44,15 @@ static inline void kfree_percpu(const vo
}
static inline void kmalloc_percpu_init(void) { }
+/* 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
+
#endif /* CONFIG_SMP */
/*
@@ -68,4 +77,9 @@ static inline void kmalloc_percpu_init(v
#define get_cpu_ptr(ptr) per_cpu_ptr(ptr, get_cpu())
#define put_cpu_ptr(ptr) put_cpu()
+#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu
+
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
+
#endif /* __LINUX_PERCPU_H */
_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
+
#endif /* __LINUX_PERCPU_H */
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH 1/3] Per-cpu UP unification 2003-05-20 1:22 [PATCH 1/3] Per-cpu UP unification Rusty Russell @ 2003-05-20 10:53 ` Andrew Morton 2003-05-21 2:02 ` Rusty Russell 0 siblings, 1 reply; 3+ messages in thread From: Andrew Morton @ 2003-05-20 10:53 UTC (permalink / raw) To: Rusty Russell; +Cc: linux-kernel, davidm, dipankar Rusty Russell <rusty@rustcorp.com.au> wrote: > > [ Untested on ia64, but fairly trivial if I've broken something ]. > > Name: Unification of per-cpu headers for non-SMP > Author: Rusty Russell > Status: Trivial I applied all these to the ppc64 kernel (you missed ppc64 btw) and it dies. Quite late in boot, during floppy_init->init_disk_stats->alloc_percpu. I'm reduced to debugging with printk on ppc64. __alloc_percpu() calls new_block(), loops around and then dies in here: #define D() printk("at %s:%d\n", __FILE__, __LINE__) D(); /* Transfer extra to previous block. */ if (b->size[i-1] < 0) b->size[i-1] -= extra; else b->size[i-1] += extra; b->size[i] -= extra; ptr += extra; D(); Not sure what happened - no oops, no xmon, no sysrq, no nuthin. It even manages to lock up minicom on the other end of the cable. Impressed. ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 1/3] Per-cpu UP unification 2003-05-20 10:53 ` Andrew Morton @ 2003-05-21 2:02 ` Rusty Russell 0 siblings, 0 replies; 3+ messages in thread From: Rusty Russell @ 2003-05-21 2:02 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, davidm, dipankar In message <20030520035322.27211c07.akpm@digeo.com> you write: > Rusty Russell <rusty@rustcorp.com.au> wrote: > > > > [ Untested on ia64, but fairly trivial if I've broken something ]. > > > > Name: Unification of per-cpu headers for non-SMP > > Author: Rusty Russell > > Status: Trivial > > I applied all these to the ppc64 kernel (you missed ppc64 btw) and it dies. > > Quite late in boot, during floppy_init->init_disk_stats->alloc_percpu. > > I'm reduced to debugging with printk on ppc64. __alloc_percpu() calls > new_block(), loops around and then dies in here: Hmm, Works For Me(TM). Here's my test code: change init_alloc_percpu() to call test_percpu() explicitly at the end (so before you hit the current bug). I'll test on bk14 here, and if that passes I'll seek a PPC64 box... Thanks! Rusty. Name: kmalloc testing patch Author: Rusty Russell Status: Tested on 2.5.69-bk13 Depends: Misc/kmalloc_percpu-full.patch.gz D: This adds simple test code to kmalloc percpu. diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal working-2.5.69-bk13-kmalloc_percpu-full/mm/percpu.c working-2.5.69-bk13-kmalloc_percpu-debug/mm/percpu.c --- working-2.5.69-bk13-kmalloc_percpu-full/mm/percpu.c 2003-05-20 12:54:21.000000000 +1000 +++ working-2.5.69-bk13-kmalloc_percpu-debug/mm/percpu.c 2003-05-20 12:53:47.000000000 +1000 @@ -245,6 +245,159 @@ void free_percpu(const void *freeme) BUG(); } +#if 1 +#include <linux/random.h> + +static void check_values(unsigned int *ptrs[], + unsigned int sizes[], + unsigned int num) +{ + unsigned int cpu, i; + unsigned char *ptr; + + if (!ptrs[num]) + return; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + ptr = (unsigned char *)per_cpu_ptr(ptrs[num], cpu); + for (i = 0; i < sizes[num]; i++) { + if (ptr[i] != (unsigned char)(num + cpu)) + BUG(); + } + } +} + +static void check_blocklen(void) +{ + struct pcpu_block *i; + unsigned int count = 0; + + list_for_each_entry(i, &pcpu_blocks, list) + count++; + + printk("Total blocks = %u\n", count); +} + +static void dump_blocks(const char *start_or_end) +{ + struct pcpu_block *i; + + list_for_each_entry(i, &pcpu_blocks, list) { + int expected_blocks = 1; + + if (i->base_ptr == percpu_base) + expected_blocks = 2; + if (i->num_used != expected_blocks) { + printk("Block %p has %u subs at %s\n", + i->base_ptr, i->num_used, start_or_end); + } + } +} + +static void mymemset(void *ptr, int c, unsigned long len) +{ + unsigned char *p = ptr; + while (len > 0) { + *p = c; + p++; + len--; + } +} + +static int random(void) +{ + unsigned short s; + + get_random_bytes(&s, sizeof(s)); + return s; +} + +static int test_percpu(void) +{ + unsigned int i, allocs, frees; + unsigned int *ptr; + static unsigned int *ptrs[PERCPU_MAX], sizes[PERCPU_MAX]; + + dump_blocks("start"); + allocs = frees = 0; + ptr = __alloc_percpu(4, 4); allocs++; + printk("This cpu = %p (%u)\n", + __get_cpu_ptr(ptr), *__get_cpu_ptr(ptr)); + for (i = 0; i < NR_CPUS; i++) { + printk("&ptr[i] == %p (%u)\n", + per_cpu_ptr(ptr, i), *per_cpu_ptr(ptr, i)); + *per_cpu_ptr(ptr, i) = i; + } + free_percpu(ptr); frees++; + + BUG_ON(allocs != frees); + + for (i = 4; i < PERCPU_MAX; i+=27) { + unsigned int j; + ptrs[i] = __alloc_percpu(i, 4); allocs++; + for (j = 0; j < NR_CPUS; j++) { + mymemset(per_cpu_ptr(ptrs[i], j), 0, i); + *per_cpu_ptr(ptrs[i], j) = i; + } + } + + for (i = 4; i < PERCPU_MAX; i+=27) { + unsigned int j; + for (j = 0; j < NR_CPUS; j++) + if (*per_cpu_ptr(ptrs[i], j) != i) + BUG(); + } + for (i = 4; i < PERCPU_MAX; i+=27) { + free_percpu(ptrs[i]); frees++; + ptrs[i] = NULL; + } + + BUG_ON(allocs != frees); + + /* Randomized test. */ + for (i = 0; i < 10000; i++) { + unsigned int j = random() % PERCPU_MAX; + if (!ptrs[j]) { + unsigned int cpu; + + sizes[j] = random() % PERCPU_MAX; + if (sizes[j] < 4) + sizes[j] = 4; + ptrs[j] = __alloc_percpu(sizes[j], 1<<(random()%L1_CACHE_SHIFT)); + allocs++; + + for (cpu = 0; cpu < NR_CPUS; cpu++) + memset(per_cpu_ptr(ptrs[j], cpu), j+cpu, + sizes[j]); + } else { + if (random() % 1000 == 0) { + printk("c\n"); + for (j = 0; j < PERCPU_MAX; j++) + check_values(ptrs, sizes, j); + } else { + check_values(ptrs, sizes, j); + free_percpu(ptrs[j]); frees++; + ptrs[j] = NULL; + } + } + if (i % (10000/10) == 0) + printk(".\n"); + } + check_blocklen(); + + for (i = 0; i < PERCPU_MAX; i++) { + if (ptrs[i]) { + free_percpu(ptrs[i]); frees++; + ptrs[i] = NULL; + } + } + BUG_ON(allocs != frees); + dump_blocks("end"); + return 0; +} +late_initcall(test_percpu); +#endif + unsigned long __per_cpu_offset[NR_CPUS]; EXPORT_SYMBOL(__per_cpu_offset); -- Anyone who quotes me in their sig is an idiot. -- Rusty Russell. ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2003-05-21 7:59 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-05-20 1:22 [PATCH 1/3] Per-cpu UP unification Rusty Russell 2003-05-20 10:53 ` Andrew Morton 2003-05-21 2:02 ` Rusty Russell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®