--- mm/slub.c | 52 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2007-10-18 12:47:53.000000000 -0700 +++ linux-2.6/mm/slub.c 2007-10-18 13:31:20.000000000 -0700 @@ -1477,6 +1477,30 @@ static inline void **get_freelist(struct return list; } +/* Free an object to the por cpu structure and return the old freelist pointer */ +static inline void **free_cpu_object(struct kmem_cache_cpu *c, void **object) +{ + void **prior; + + prior = c->freelist; + object[c->offset] = prior; + c->freelist = object; + return prior; +} + +/* + * Allocate object from the per cpu structure. + */ +static inline void **alloc_cpu_object(struct kmem_cache_cpu *c) +{ + void **object; + + object = c->freelist; + if (object) + c->freelist = object[c->offset]; + return object; +} + /* * Remove the cpu slab */ @@ -1671,20 +1695,25 @@ static void __always_inline *slab_alloc( local_irq_save(flags); c = get_cpu_slab(s, smp_processor_id()); - if (unlikely(!c->freelist || !node_match(c, node))) - - object = __slab_alloc(s, gfpflags, node, addr, c); + if (unlikely(!node_match(c, node))) + goto slow; - else { - object = c->freelist; - c->freelist = object[c->offset]; - } + object = alloc_cpu_object(c); + if (unlikely(!object)) + goto slow; +back: local_irq_restore(flags); - if (unlikely((gfpflags & __GFP_ZERO) && object)) + if (unlikely((gfpflags & __GFP_ZERO))) memset(object, 0, c->objsize); return object; + +slow: + object = __slab_alloc(s, gfpflags, node, addr, c); + if (object) + goto back; + return NULL; } void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) @@ -1755,10 +1784,9 @@ static void __always_inline slab_free(st local_irq_save(flags); 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; - } else + if (likely(page == c->page && c->node >= 0)) + free_cpu_object(c, object); + else __slab_free(s, page, x, addr, c->offset); local_irq_restore(flags);