--- Documentation/vm/slabinfo.c | 7 +++++++ include/linux/slub_def.h | 2 ++ mm/slub.c | 29 ++++++++++++++++++++--------- 3 files changed, 29 insertions(+), 9 deletions(-) Index: linux-2.6/include/linux/slub_def.h =================================================================== --- linux-2.6.orig/include/linux/slub_def.h 2008-03-27 16:50:34.344612794 -0700 +++ linux-2.6/include/linux/slub_def.h 2008-03-27 16:51:11.668894552 -0700 @@ -30,6 +30,8 @@ enum stat_item { DEACTIVATE_TO_TAIL, /* Cpu slab was moved to the tail of partials */ DEACTIVATE_REMOTE_FREES,/* Slab contained remotely freed objects */ ORDER_FALLBACK, /* Number of times fallback was necessary */ + CONTENTION_ALLOC, /* slab lock contention on alloc */ + CONTENTION_FREE, /* slab lock contention on free */ NR_SLUB_STAT_ITEMS }; struct kmem_cache_cpu { Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2008-03-27 16:51:18.556946456 -0700 +++ linux-2.6/mm/slub.c 2008-03-27 17:16:34.405210283 -0700 @@ -1210,11 +1210,6 @@ static void discard_slab(struct kmem_cac /* * Per slab locking using the pagelock */ -static __always_inline void slab_lock(struct page *page) -{ - bit_spin_lock(PG_locked, &page->flags); -} - static __always_inline void slab_unlock(struct page *page) { __bit_spin_unlock(PG_locked, &page->flags); @@ -1228,6 +1223,17 @@ static __always_inline int slab_trylock( return rc; } +static __always_inline void slab_lock(struct page *page, + struct kmem_cache_cpu *c, int counter) +{ +#ifdef CONFIG_SLUB_STATS + if (slab_trylock(page)) + return; + stat(c, counter); +#endif + bit_spin_lock(PG_locked, &page->flags); +} + /* * Management of partially allocated slabs */ @@ -1444,7 +1450,8 @@ static void deactivate_slab(struct kmem_ static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { stat(c, CPUSLAB_FLUSH); - slab_lock(c->page); + slab_lock(c->page, get_cpu_slab(s, raw_smp_processor_id()), + CONTENTION_FREE); deactivate_slab(s, c); } @@ -1521,7 +1528,7 @@ static void *__slab_alloc(struct kmem_ca if (!c->page) goto new_slab; - slab_lock(c->page); + slab_lock(c->page, c, CONTENTION_ALLOC); if (unlikely(!node_match(c, node))) goto another_slab; @@ -1567,7 +1574,7 @@ new_slab: stat(c, ALLOC_SLAB); if (c->page) flush_slab(s, c); - slab_lock(new); + slab_lock(new, c, CONTENTION_ALLOC); SetSlabFrozen(new); c->page = new; goto load_freelist; @@ -1650,7 +1657,7 @@ static void __slab_free(struct kmem_cach c = get_cpu_slab(s, raw_smp_processor_id()); stat(c, FREE_SLOWPATH); - slab_lock(page); + slab_lock(page, c, CONTENTION_FREE); if (unlikely(SlabDebug(page))) goto debug; @@ -4085,6 +4092,8 @@ STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail); STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees); STAT_ATTR(ORDER_FALLBACK, order_fallback); +STAT_ATTR(CONTENTION_ALLOC, contention_alloc); +STAT_ATTR(CONTENTION_FREE, contention_free); #endif static struct attribute *slab_attrs[] = { @@ -4138,6 +4147,8 @@ static struct attribute *slab_attrs[] = &deactivate_to_tail_attr.attr, &deactivate_remote_frees_attr.attr, &order_fallback_attr.attr, + &contention_alloc_attr.attr, + &contention_free_attr.attr, #endif NULL }; Index: linux-2.6/Documentation/vm/slabinfo.c =================================================================== --- linux-2.6.orig/Documentation/vm/slabinfo.c 2008-03-27 16:56:05.658879168 -0700 +++ linux-2.6/Documentation/vm/slabinfo.c 2008-03-27 16:58:24.555685606 -0700 @@ -34,6 +34,7 @@ struct slabinfo { unsigned long partial, objects, slabs, objects_partial, objects_total; unsigned long alloc_fastpath, alloc_slowpath; unsigned long free_fastpath, free_slowpath; + unsigned long contention_free, contention_alloc; unsigned long free_frozen, free_add_partial, free_remove_partial; unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill; unsigned long cpuslab_flush, deactivate_full, deactivate_empty; @@ -430,6 +431,10 @@ void slab_stats(struct slabinfo *s) printf("\n"); printf("Slab Perf Counter Alloc Free %%Al %%Fr\n"); printf("--------------------------------------------------\n"); + printf("Contention %8lu %8lu %3lu %3lu\n", + s->contention_alloc, s->contention_free, + s->contention_alloc * 100 / total_alloc, + s->contention_free * 100 / total_free); printf("Fastpath %8lu %8lu %3lu %3lu\n", s->alloc_fastpath, s->free_fastpath, s->alloc_fastpath * 100 / total_alloc, @@ -1175,6 +1180,8 @@ void read_slab_dir(void) slab->alloc_slowpath = get_obj("alloc_slowpath"); slab->free_fastpath = get_obj("free_fastpath"); slab->free_slowpath = get_obj("free_slowpath"); + slab->contention_free = get_obj("contention_free"); + slab->contention_alloc = get_obj("contention_alloc"); slab->free_frozen= get_obj("free_frozen"); slab->free_add_partial = get_obj("free_add_partial"); slab->free_remove_partial = get_obj("free_remove_partial");