Subject: this_cpu: Convert slub to the use of allocpercpu/this_cpu ops. Signed-off-by: Christoph Lameter --- mm/slub.c | 76 +++++++++++++++++++++++++++++--------------------------------- 1 file changed, 36 insertions(+), 40 deletions(-) Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2009-05-28 16:03:17.000000000 -0500 +++ linux-2.6/mm/slub.c 2009-05-28 16:06:29.000000000 -0500 @@ -209,10 +209,10 @@ static inline void sysfs_slab_remove(str #endif -static inline void stat(struct kmem_cache_cpu *c, enum stat_item si) +static inline void stat(struct kmem_cache *s, enum stat_item si) { #ifdef CONFIG_SLUB_STATS - c->stat[si]++; + __this_cpu_inc(s->cpu_slab->stat[si]); #endif } @@ -1073,7 +1073,7 @@ static struct page *allocate_slab(struct if (!page) return NULL; - stat(my_cpu_ptr(s->cpu_slab), ORDER_FALLBACK); + stat(s, ORDER_FALLBACK); } page->objects = oo_objects(oo); mod_zone_page_state(page_zone(page), @@ -1352,23 +1352,22 @@ static struct page *get_partial(struct k static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail) { struct kmem_cache_node *n = get_node(s, page_to_nid(page)); - struct kmem_cache_cpu *c = my_cpu_ptr(s->cpu_slab); __ClearPageSlubFrozen(page); if (page->inuse) { if (page->freelist) { add_partial(n, page, tail); - stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD); + stat(s, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD); } else { - stat(c, DEACTIVATE_FULL); + stat(s, DEACTIVATE_FULL); if (SLABDEBUG && PageSlubDebug(page) && (s->flags & SLAB_STORE_USER)) add_full(n, page); } slab_unlock(page); } else { - stat(c, DEACTIVATE_EMPTY); + stat(s, DEACTIVATE_EMPTY); if (n->nr_partial < s->min_partial) { /* * Adding an empty slab to the partial slabs in order @@ -1384,7 +1383,7 @@ static void unfreeze_slab(struct kmem_ca slab_unlock(page); } else { slab_unlock(page); - stat(__my_cpu_ptr(s->cpu_slab), FREE_SLAB); + stat(s, FREE_SLAB); discard_slab(s, page); } } @@ -1399,7 +1398,7 @@ static void deactivate_slab(struct kmem_ int tail = 1; if (page->freelist) - stat(c, DEACTIVATE_REMOTE_FREES); + stat(s, DEACTIVATE_REMOTE_FREES); /* * Merge cpu freelist into slab freelist. Typically we get here * because both freelists are empty. So this is unlikely @@ -1425,7 +1424,7 @@ static void deactivate_slab(struct kmem_ static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { - stat(c, CPUSLAB_FLUSH); + stat(s, CPUSLAB_FLUSH); slab_lock(c->page); deactivate_slab(s, c); } @@ -1459,10 +1458,10 @@ static void flush_all(struct kmem_cache * Check if the objects in a per cpu structure fit numa * locality expectations. */ -static inline int node_match(struct kmem_cache_cpu *c, int node) +static inline int node_match(struct kmem_cache *s, int node) { #ifdef CONFIG_NUMA - if (node != -1 && c->node != node) + if (node != -1 && __this_cpu_read(s->cpu_slab->node) != node) return 0; #endif return 1; @@ -1487,19 +1486,20 @@ static inline int node_match(struct kmem * a call to the page allocator and the setup of a new slab. */ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, - unsigned long addr, struct kmem_cache_cpu *c) + unsigned long addr) { void **object; + struct kmem_cache_cpu *c = __this_cpu_ptr(s->cpu_slab); struct page *new; if (!c->page) goto new_slab; slab_lock(c->page); - if (unlikely(!node_match(c, node))) + if (unlikely(!node_match(s, node))) goto another_slab; - stat(c, ALLOC_REFILL); + stat(s, ALLOC_REFILL); load_freelist: object = c->page->freelist; @@ -1514,7 +1514,7 @@ load_freelist: c->node = page_to_nid(c->page); unlock_out: slab_unlock(c->page); - stat(c, ALLOC_SLOWPATH); + stat(s, ALLOC_SLOWPATH); return object; another_slab: @@ -1524,7 +1524,7 @@ new_slab: new = get_partial(s, gfpflags, node); if (new) { c->page = new; - stat(c, ALLOC_FROM_PARTIAL); + stat(s, ALLOC_FROM_PARTIAL); goto load_freelist; } @@ -1537,8 +1537,8 @@ new_slab: local_irq_disable(); if (new) { - c = __my_cpu_ptr(s->cpu_slab); - stat(c, ALLOC_SLAB); + c = __this_cpu_ptr(s->cpu_slab); + stat(s, ALLOC_SLAB); if (c->page) flush_slab(s, c); slab_lock(new); @@ -1571,7 +1571,6 @@ static __always_inline void *slab_alloc( gfp_t gfpflags, int node, unsigned long addr) { void **object; - struct kmem_cache_cpu *c; unsigned long flags; lockdep_trace_alloc(gfpflags); @@ -1581,15 +1580,14 @@ static __always_inline void *slab_alloc( return NULL; local_irq_save(flags); - c = __my_cpu_ptr(s->cpu_slab); - object = c->freelist; - if (unlikely(!object || !node_match(c, node))) + object = __this_cpu_read(s->cpu_slab->freelist); + if (unlikely(!object || !node_match(s, node))) - object = __slab_alloc(s, gfpflags, node, addr, c); + object = __slab_alloc(s, gfpflags, node, addr); else { - c->freelist = get_freepointer(s, object); - stat(c, ALLOC_FASTPATH); + __this_cpu_write(s->cpu_slab->freelist, get_freepointer(s, object)); + stat(s, ALLOC_FASTPATH); } local_irq_restore(flags); @@ -1653,10 +1651,8 @@ static void __slab_free(struct kmem_cach { void *prior; void **object = (void *)x; - struct kmem_cache_cpu *c; - c = __my_cpu_ptr(s->cpu_slab); - stat(c, FREE_SLOWPATH); + stat(s, FREE_SLOWPATH); slab_lock(page); if (unlikely(SLABDEBUG && PageSlubDebug(page))) @@ -1669,7 +1665,7 @@ checks_ok: page->inuse--; if (unlikely(PageSlubFrozen(page))) { - stat(c, FREE_FROZEN); + stat(s, FREE_FROZEN); goto out_unlock; } @@ -1682,7 +1678,7 @@ checks_ok: */ if (unlikely(!prior)) { add_partial(get_node(s, page_to_nid(page)), page, 1); - stat(c, FREE_ADD_PARTIAL); + stat(s, FREE_ADD_PARTIAL); } out_unlock: @@ -1695,10 +1691,10 @@ slab_empty: * Slab still on the partial list. */ remove_partial(s, page); - stat(c, FREE_REMOVE_PARTIAL); + stat(s, FREE_REMOVE_PARTIAL); } slab_unlock(page); - stat(c, FREE_SLAB); + stat(s, FREE_SLAB); discard_slab(s, page); return; @@ -1723,18 +1719,18 @@ static __always_inline void slab_free(st struct page *page, void *x, unsigned long addr) { void **object = (void *)x; - struct kmem_cache_cpu *c; unsigned long flags; - local_irq_save(flags); - c = __my_cpu_ptr(s->cpu_slab); debug_check_no_locks_freed(object, s->objsize); if (!(s->flags & SLAB_DEBUG_OBJECTS)) debug_check_no_obj_freed(object, s->objsize); - if (likely(page == c->page && c->node >= 0)) { - set_freepointer(s, object, c->freelist); - c->freelist = object; - stat(c, FREE_FASTPATH); + + local_irq_save(flags); + if (likely(page == __this_cpu_read(s->cpu_slab->page) && + __this_cpu_read(s->cpu_slab->node) >= 0)) { + set_freepointer(s, object, __this_cpu_read(s->cpu_slab->freelist)); + __this_cpu_write(s->cpu_slab->freelist, object); + stat(s, FREE_FASTPATH); } else __slab_free(s, page, x, addr);