--- include/linux/slub_def.h | 5 ++++- mm/slub.c | 36 ++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 17 deletions(-) Index: linux-2.6/include/linux/slub_def.h =================================================================== --- linux-2.6.orig/include/linux/slub_def.h 2008-02-06 22:03:57.699717735 -0800 +++ linux-2.6/include/linux/slub_def.h 2008-02-06 22:16:07.273239359 -0800 @@ -11,12 +11,15 @@ #include #include +#define SLUB_QSIZE 512 + struct kmem_cache_cpu { - void **freelist; /* Pointer to first free per cpu object */ + void **next; /* Pointer to the next free object */ struct page *page; /* The slab from which we are allocating */ int node; /* The node of the page (or -1 for debug) */ unsigned int offset; /* Freepointer offset (in word units) */ unsigned int objsize; /* Size of an object (from kmem_cache) */ + void *queue[SLUB_QSIZE]; /* per cpu queue */ }; struct kmem_cache_node { Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2008-02-06 22:03:57.707717882 -0800 +++ linux-2.6/mm/slub.c 2008-02-06 22:16:07.273239359 -0800 @@ -1378,14 +1378,13 @@ static void deactivate_slab(struct kmem_ * because both freelists are empty. So this is unlikely * to occur. */ - while (unlikely(c->freelist)) { + while (unlikely(c->next > c->queue)) { void **object; tail = 0; /* Hot objects. Put the slab first */ /* Retrieve object from cpu_freelist */ - object = c->freelist; - c->freelist = c->freelist[c->offset]; + object = *--c->next; /* And put onto the regular freelist */ object[c->offset] = page->freelist; @@ -1467,7 +1466,7 @@ static inline int node_match(struct kmem static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, void *addr, struct kmem_cache_cpu *c) { - void **object; + void **object, **q; struct page *new; if (!c->page) @@ -1483,8 +1482,15 @@ load_freelist: if (unlikely(SlabDebug(c->page))) goto debug; - object = c->page->freelist; - c->freelist = object[c->offset]; + q = c->page->freelist; + object = q; + c->next = c->queue; + for ( ; ; ) { + q = q[c->offset]; + if (!q) + break; + *c->next++ = q; + } c->page->inuse = s->objects; c->page->freelist = NULL; c->node = page_to_nid(c->page); @@ -1550,14 +1556,13 @@ static __always_inline void *slab_alloc( local_irq_save(flags); c = get_cpu_slab(s, smp_processor_id()); - if (unlikely(!c->freelist || !node_match(c, node))) + if (unlikely(c->next == c->queue || !node_match(c, node))) object = __slab_alloc(s, gfpflags, node, addr, c); - else { - object = c->freelist; - c->freelist = object[c->offset]; - } + else + object = *--c->next; + local_irq_restore(flags); if (unlikely((gfpflags & __GFP_ZERO) && object)) @@ -1660,8 +1665,7 @@ static __always_inline void slab_free(st debug_check_no_locks_freed(object, s->objsize); c = get_cpu_slab(s, smp_processor_id()); if (likely(page == c->page && c->node >= 0)) { - object[c->offset] = c->freelist; - c->freelist = object; + *c->next++ = object; } else __slab_free(s, page, x, addr, c->offset); @@ -1842,7 +1846,7 @@ static void init_kmem_cache_cpu(struct k struct kmem_cache_cpu *c) { c->page = NULL; - c->freelist = NULL; + c->next = c->queue; c->node = 0; c->offset = s->offset / sizeof(void *); c->objsize = s->objsize; @@ -1890,7 +1894,7 @@ static struct kmem_cache_cpu *alloc_kmem if (c) per_cpu(kmem_cache_cpu_free, cpu) = - (void *)c->freelist; + (void *)c->next; else { /* Table overflow: So allocate ourselves */ c = kmalloc_node( @@ -1911,7 +1915,7 @@ static void free_kmem_cache_cpu(struct k kfree(c); return; } - c->freelist = (void *)per_cpu(kmem_cache_cpu_free, cpu); + c->next = (void *)per_cpu(kmem_cache_cpu_free, cpu); per_cpu(kmem_cache_cpu_free, cpu) = c; }