Manfred Spraul wrote:
> Hi,
>
> kmalloc(constant,GFP_KERNEL) spends a singificant amount of time in the
> initial loop that finds the correct cache. For constant allocations, the
> correct cache can be indentified at compile time.
>
> What do you think about the attached patch? It's not pretty, but it
> should work will all gcc versions. Any other ideas?
> Just FYI: The function that forced me to use use switch/case instead of
> if is interrupts_open in fs/proc/proc_misc.c.
How about this? GCC 3.2.2 is able to optimize it away properly from the
tests that I've run.
-- Brian Gerst
diff -ur linux-2.5.70-bk/include/linux/slab.h linux/include/linux/slab.h --- linux-2.5.70-bk/include/linux/slab.h 2003-05-26 22:27:29.000000000 -0400 +++ linux/include/linux/slab.h 2003-06-09 17:24:40.000000000 -0400 @@ -62,7 +62,36 @@ extern void kmem_cache_free(kmem_cache_t *, void *); extern unsigned int kmem_cache_size(kmem_cache_t *); -extern void *kmalloc(size_t, int); +/* Size description struct for general caches. */ +struct cache_sizes { + size_t cs_size; + kmem_cache_t *cs_cachep; + kmem_cache_t *cs_dmacachep; +}; +extern struct cache_sizes malloc_sizes[]; +extern void *__kmalloc(size_t, int); + +static inline void *kmalloc(size_t size, int flags) +{ + if (__builtin_constant_p(size)) { + int i = 0; +#define CACHE(x) \ + if (size <= x) \ + goto found; \ + else \ + i++; +#include "kmalloc_sizes.h" +#undef CACHE + extern void __you_cannot_kmalloc_that_much(void); + __you_cannot_kmalloc_that_much(); +found: + return kmem_cache_alloc((flags & GFP_DMA) ? + malloc_sizes[i].cs_dmacachep : + malloc_sizes[i].cs_cachep, flags); + } + return __kmalloc(size, flags); +} + extern void kfree(const void *); extern unsigned int ksize(const void *); diff -ur linux-2.5.70-bk/kernel/ksyms.c linux/kernel/ksyms.c --- linux-2.5.70-bk/kernel/ksyms.c 2003-06-08 23:50:12.000000000 -0400 +++ linux/kernel/ksyms.c 2003-06-09 16:44:27.000000000 -0400 @@ -95,7 +95,8 @@ EXPORT_SYMBOL(kmem_cache_size); EXPORT_SYMBOL(set_shrinker); EXPORT_SYMBOL(remove_shrinker); -EXPORT_SYMBOL(kmalloc); +EXPORT_SYMBOL(malloc_sizes); +EXPORT_SYMBOL(__kmalloc); EXPORT_SYMBOL(kfree); #ifdef CONFIG_SMP EXPORT_SYMBOL(__alloc_percpu); diff -ur linux-2.5.70-bk/mm/slab.c linux/mm/slab.c --- linux-2.5.70-bk/mm/slab.c 2003-06-08 23:50:13.000000000 -0400 +++ linux/mm/slab.c 2003-06-09 16:43:55.000000000 -0400 @@ -385,11 +385,7 @@ #define GET_PAGE_SLAB(pg) ((struct slab *)(pg)->list.prev) /* These are the default caches for kmalloc. Custom caches can have other sizes. */ -static struct cache_sizes { - size_t cs_size; - kmem_cache_t *cs_cachep; - kmem_cache_t *cs_dmacachep; -} malloc_sizes[] = { +struct cache_sizes malloc_sizes[] = { #define CACHE(x) { .cs_size = (x) }, #include <linux/kmalloc_sizes.h> { 0, } @@ -1967,7 +1963,7 @@ * platforms. For example, on i386, it means that the memory must come * from the first 16MB. */ -void * kmalloc (size_t size, int flags) +void * __kmalloc (size_t size, int flags) { struct cache_sizes *csizep = malloc_sizes;
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sun Jun 15 2003 - 22:00:22 EST