内存管理-SLAB(创建SLAB块cache_grow())

从buddy system给cache分配新的slab。


static int cache_grow (kmem_cache_t * cachep, int flags, int nodeid)
{
struct slab *slabp;
void *objp;
size_t  offset;
int  local_flags;
unsigned long  ctor_flags;

/* Be lazy and only check for valid flags here,
   * keeping it out of the critical path in kmem_cache_alloc().
 */
if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW))
BUG();
if (flags & SLAB_NO_GROW)
return 0;

ctor_flags = SLAB_CTOR_CONSTRUCTOR;
local_flags = (flags & SLAB_LEVEL_MASK);
if (!(local_flags & __GFP_WAIT))
/*
 * Not allowed to sleep.  Need to tell a constructor about
 * this - it might need to know...
 */
ctor_flags |= SLAB_CTOR_ATOMIC;

/* About to mess with non-constant members - lock. */
check_irq_off();
spin_lock(&cachep->spinlock);

/* Get colour for the slab, and cal the next value. */
/*获得颜色*/
offset = cachep->colour_next;
/*获得下一个颜色*/
cachep->colour_next++;
if (cachep->colour_next >= cachep->colour)
cachep->colour_next = 0;
/*得到偏移量*/
offset *= cachep->colour_off;
spin_unlock(&cachep->spinlock);
if (local_flags & __GFP_WAIT)
local_irq_enable();
/*
 * The test for missing atomic flag is performed here, rather than
 * the more obvious place, simply to reduce the critical path length
 * in kmem_cache_alloc(). If a caller is seriously mis-behaving they
 * will eventually be caught here (where it matters).
 */
kmem_flagcheck(cachep, flags);
/*获得slab对应的物理页*/
if (!(objp = kmem_getpages(cachep, flags, nodeid)))
goto failed;
/*获得slab描述符*/
if (!(slabp = alloc_slabmgmt(cachep, objp, offset, local_flags)))
goto opps1;
/*设置属性*/
set_slab_attr(cachep, slabp, objp);
/*初始化slab中的对象*/
cache_init_objs(cachep, slabp, ctor_flags);

if (local_flags & __GFP_WAIT)
local_irq_disable();
check_irq_off();
spin_lock(&cachep->spinlock);

/*将新分配的slab添加到slabs_free*/
list_add_tail(&slabp->list, &(list3_data(cachep)->slabs_free));
STATS_INC_GROWN(cachep);
list3_data(cachep)->free_objects += cachep->num;
spin_unlock(&cachep->spinlock);
return 1;
opps1:
kmem_freepages(cachep, objp);
failed:
if (local_flags & __GFP_WAIT)
local_irq_disable();
return 0;
}


static void *kmem_getpages(kmem_cache_t *cachep, int flags, int nodeid)
{
struct page *page;
void *addr;
int i;

flags |= cachep->gfpflags;
/*如果没有指定节点,则从本节点分配*/
if (likely(nodeid == -1)) {
page = alloc_pages(flags, cachep->gfporder);
} else {
/*如果指定了节点,则从指定的节点分配*/
page = alloc_pages_node(nodeid, flags, cachep->gfporder);
}
if (!page)
return NULL;
/*获得slab第一个页的线性地址*/
addr = page_address(page);
/*获得物理页的数量*/
i = (1 << cachep->gfporder);
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
atomic_add(i, &slab_reclaim_pages);
add_page_state(nr_slab, i);
/*设置每页的标志位为slab的*/
while (i--) {
SetPageSlab(page);
page++;
}
return addr;
}

static struct slab* alloc_slabmgmt (kmem_cache_t *cachep,
void *objp, int colour_off, int local_flags)
{
struct slab *slabp;
/*如果内存描述符是外置的*/
if (OFF_SLAB(cachep)) {
/*则从在kmem_cache_create()中指定的cache中分配*/
slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
if (!slabp)
return NULL;
} else {
slabp = objp+colour_off;
colour_off += cachep->slab_size;
}
slabp->inuse = 0;
slabp->colouroff = colour_off;
slabp->s_mem = objp+colour_off;

return slabp;
}

static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
{
int i;
struct page *page;

/* Nasty!!!!!! I hope this is OK. */
i = 1 << cachep->gfporder;
/*获得对象的第一个页的页描述符*/
page = virt_to_page(objp);
do {
/*将高速缓存描述符赋给页描述符中lru字段的next字段*/
SET_PAGE_CACHE(page, cachep);
/*将slab描述符赋给页描述符中lru字段的prev字段*/
SET_PAGE_SLAB(page, slabp);
page++;
} while (--i);
}

static void cache_init_objs (kmem_cache_t * cachep,
struct slab * slabp, unsigned long ctor_flags)
{
int i;

for (i = 0; i < cachep->num; i++) {
/*获得slab中每个对象的地址*/
void* objp = slabp->s_mem+cachep->objsize*i;
#if DEBUG
/* need to poison the objs? */
if (cachep->flags & SLAB_POISON)
poison_obj(cachep, objp, POISON_FREE);
if (cachep->flags & SLAB_STORE_USER)
*dbg_userword(cachep, objp) = NULL;

if (cachep->flags & SLAB_RED_ZONE) {
*dbg_redzone1(cachep, objp) = RED_INACTIVE;
*dbg_redzone2(cachep, objp) = RED_INACTIVE;
}
/*
 * Constructors are not allowed to allocate memory from
 * the same cache which they are a constructor for.
 * Otherwise, deadlock. They must also be threaded.
 */
if (cachep->ctor && !(cachep->flags & SLAB_POISON))
cachep->ctor(objp+obj_dbghead(cachep), cachep, ctor_flags);

if (cachep->flags & SLAB_RED_ZONE) {
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "constructor overwrote the"
" end of an object");
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "constructor overwrote the"
" start of an object");
}
if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
        kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
#else           /*调用构造函数初始化每一个对象*/
if (cachep->ctor)
cachep->ctor(objp, cachep, ctor_flags);
#endif
/*指向下一个空闲对象*/
slab_bufctl(slabp)[i] = i+1;
}
slab_bufctl(slabp)[i-1] = BUFCTL_END;
slabp->free = 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值