1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | static __always_inline void *slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, void *addr) { void **object; struct kmem_cache_cpu *c; unsigned long flags; local_irq_save(flags); c = get_cpu_slab(s, smp_processor_id()); (a) if (unlikely(!c->freelist || !node_match(c, node))) object = __slab_alloc(s, gfpflags, node, addr, c); (b) else { object = c->freelist; (c) c->freelist = object[c->offset]; stat(c, ALLOC_FASTPATH); } local_irq_restore(flags); if (unlikely((gfpflags & __GFP_ZERO) && object)) memset(object, 0, c->objsize); return object; (d) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, void *addr, struct kmem_cache_cpu *c) { void **object; struct page *new; gfpflags &= ~__GFP_ZERO; if (!c->page) (a) goto new_slab; slab_lock(c->page); if (unlikely(!node_match(c, node))) (b) goto another_slab; stat(c, ALLOC_REFILL); load_freelist: object = c->page->freelist; if (unlikely(!object)) (c) goto another_slab; if (unlikely(SlabDebug(c->page))) goto debug; c->freelist = object[c->offset]; (d) c->page->inuse = s->objects; c->page->freelist = NULL; c->node = page_to_nid(c->page); unlock_out: slab_unlock(c->page); stat(c, ALLOC_SLOWPATH); return object; another_slab: deactivate_slab(s, c); (e) new_slab: new = get_partial(s, gfpflags, node); (f) if (new) { c->page = new; stat(c, ALLOC_FROM_PARTIAL); goto load_freelist; } if (gfpflags & __GFP_WAIT) (g) local_irq_enable(); new = new_slab(s, gfpflags, node); (h) if (gfpflags & __GFP_WAIT) local_irq_disable(); if (new) { c = get_cpu_slab(s, smp_processor_id()); stat(c, ALLOC_SLAB); if (c->page) flush_slab(s, c); slab_lock(new); SetSlabFrozen(new); c->page = new; goto load_freelist; } if (!(gfpflags & __GFP_NORETRY) && (s->flags & __PAGE_ALLOC_FALLBACK)) { if (gfpflags & __GFP_WAIT) local_irq_enable(); object = kmalloc_large(s->objsize, gfpflags); (i) if (gfpflags & __GFP_WAIT) local_irq_disable(); return object; } return NULL; debug: if (!alloc_debug_processing(s, c->page, object, addr)) goto another_slab; c->page->inuse++; c->page->freelist = object[c->offset]; c->node = -1; goto unlock_out; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | static __always_inline void slab_free(struct kmem_cache *s, struct page *page, void *x, void *addr) { void **object = (void *)x; struct kmem_cache_cpu *c; unsigned long flags; local_irq_save(flags); c = get_cpu_slab(s, smp_processor_id()); debug_check_no_locks_freed(object, c->objsize); if (likely(page == c->page && c->node >= 0)) { (a) object[c->offset] = c->freelist; c->freelist = object; stat(c, FREE_FASTPATH); } else __slab_free(s, page, x, addr, c->offset); (b) local_irq_restore(flags); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | static void __slab_free(struct kmem_cache *s, struct page *page, void *x, void *addr, unsigned int offset) { void *prior; void **object = (void *)x; struct kmem_cache_cpu *c; c = get_cpu_slab(s, raw_smp_processor_id()); stat(c, FREE_SLOWPATH); slab_lock(page); if (unlikely(SlabDebug(page))) goto debug; checks_ok: prior = object[offset] = page->freelist; (a) page->freelist = object; page->inuse--; if (unlikely(SlabFrozen(page))) { stat(c, FREE_FROZEN); goto out_unlock; } if (unlikely(!page->inuse)) (b) goto slab_empty; if (unlikely(!prior)) { (c) add_partial(get_node(s, page_to_nid(page)), page, 1); stat(c, FREE_ADD_PARTIAL); } out_unlock: slab_unlock(page); return; slab_empty: if (prior) { (d) remove_partial(s, page); stat(c, FREE_REMOVE_PARTIAL); } slab_unlock(page); stat(c, FREE_SLAB); discard_slab(s, page); return; debug: if (!free_debug_processing(s, page, x, addr)) goto out_unlock; goto checks_ok; } |
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |