您的位置:首页 > 其它

内存管理API之mempool_resize

2018-02-03 08:11 363 查看
int mempool_resize(mempool_t *pool, int new_min_nr)用于改变已经存在的缓存池能提供最小缓存的大小
其源码分析如下:
int mempool_resize(mempool_t *pool, int new_min_nr)
{
void *element;
void **new_elements;
unsigned long flags;
#缓存size 小于零,则打印当前的callstack
BUG_ON(new_min_nr <= 0);
#这个函数不能sleep
might_sleep();
#因此new_min_nr小于已经存在的min_nr的话,则将在min_nr中的多余的memory 释放掉,
#例如原来能提供64 byte,但是现在形参new_min_nr 等于48,则这里要将16 byte的memory 释放掉。
spin_lock_irqsave(&pool->lock, flags);
if (new_min_nr <= pool->min_nr) {
while (new_min_nr < pool->curr_nr) {
element = remove_element(pool, GFP_KERNEL);
spin_unlock_irqrestore(&pool->lock, flags);
pool->free(element, pool->pool_data);
spin_lock_irqsave(&pool->lock, flags);
}
pool->min_nr = new_min_nr;
#将多余的缓存释放掉后,这个函数就退出了
goto out_unlock;
}
spin_unlock_irqrestore(&pool->lock, flags);

/* Grow the pool */
#这里是第二种情况,就是要扩大缓存池的大小,这里重新通过kmalloc_array 申请一个数组,这里也
#可以看到缓存池提供的memory都是物理连续的
new_elements = kmalloc_array(new_min_nr, sizeof(*new_elements),
GFP_KERNEL);
if (!new_elements)
return -ENOMEM;

spin_lock_irqsave(&pool->lock, flags);
#这种case就缓存池缩小的case,前面已经检查分析过了,这里在检查一次
if (unlikely(new_min_nr <= pool->min_nr)) {
/* Raced, other resize will do our work */
spin_unlock_irqrestore(&pool->lock, flags);
kfree(new_elements);
goto out;
}
#将老的缓存池中的内容cp到新的缓存池中
memcpy(new_elements, pool->elements,
pool->curr_nr * sizeof(*new_elements));
kfree(pool->elements);
#更新新的缓存池指针和能提供的最小缓存size
pool->elements = new_elements;
pool->min_nr = new_min_nr;
#由于缓存池能提供的最小缓存的size 变大了,因此这里要检查一下当前能提供的缓存释放已经小于最小值了
while (pool->curr_nr < pool->min_nr) {
spin_unlock_irqrestore(&pool->lock, flags);
#能提供的缓存已经小于最小值的话,这里重新申请memory
element = pool->alloc(GFP_KERNEL, pool->pool_data);
if (!element)
goto out;
spin_lock_irqsave(&pool->lock, flags);
#将新申请的内存添加到list中,这里不明白为啥还有else的case,这里while循环已经可以保证else的case 不成立,这里又有锁保护。
if (pool->curr_nr < pool->min_nr) {
add_element(pool, element);
} else {
spin_unlock_irqrestore(&pool->lock, flags);
pool->free(element, pool->pool_data);	/* Raced */
goto out;
}
}
out_unlock:
spin_unlock_irqrestore(&pool->lock, flags);
out:
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: