#include
void
_pool_init_fixed (void **pool_ptr, u32 elt_size, u32 max_elts)
{
u8 *mmap_base;
u64 vector_size;
u64 free_index_size;
u64 total_size;
u64 page_size;
pool_header_t *fh;
vec_header_t *vh;
u8 *v;
u32 *fi;
u32 i;
u32 set_bits;
ASSERT (elt_size);
ASSERT (max_elts);
此函数用于使用预申请方式从系统获取内存池对应的内存空间。
每个内存块大小必须大于0
内存块个数必须大于0
vector_size = pool_aligned_header_bytes + vec_header_bytes (0)
+ (u64) elt_size *max_elts;
free_index_size = vec_header_bytes (0) + sizeof (u32) * max_elts;
/* Round up to a cache line boundary */
vector_size = (vector_size + CLIB_CACHE_LINE_BYTES - 1)
& ~(CLIB_CACHE_LINE_BYTES - 1);
free_index_size = (free_index_size + CLIB_CACHE_LINE_BYTES - 1)
& ~(CLIB_CACHE_LINE_BYTES - 1);
total_size = vector_size + free_index_size;
用于存放内存块的内存大小为vector_size,由pool头部,向量头部,向量数据部分共同构成。
每一个空闲内存块编号占用32位的空间,也需要预先申请好内存。
这2种内存都需要对齐到缓存线上,这样效率才高。
total_size = vector_size + free_index_size;
/* Round up to an even number of pages */
page_size = clib_mem_get_page_size ();
total_size = (total_size + page_size - 1) & ~(page_size - 1);
/* mmap demand zero memory */
mmap_base = mmap (0, total_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mmap_base == MAP_FAILED)
{
clib_unix_warning ("mmap");
*pool_ptr = 0;
}
上述2种内存加起来,就是我们需要向系统预申请的内存大小。使用mmap匿名映射来申请内存。
/* First comes the pool header */
fh = (pool_header_t *) mmap_base;
/* Find the user vector pointer */
v = (u8 *) (mmap_base + pool_aligned_header_bytes);
/* Finally, the vector header */
vh = _vec_find (v);
fh->free_bitmap = 0; /* No free elts (yet) */
fh->max_elts = max_elts;
fh->mmap_base = mmap_base;
fh->mmap_size = total_size;
内存申请到后,先初始化内存池的头部。这个时候注意,没有空闲内存块位图。空闲块位图后面需要时再申请内存。
vh->len = max_elts;
/* Build the free-index vector */
vh = (vec_header_t *) (v + vector_size);
vh->len = max_elts;
fi = (u32 *) (vh + 1);
fh->free_indices = fi;
然后初始化空闲块编号向量。
/* Set the entire free bitmap */
clib_bitmap_alloc (fh->free_bitmap, max_elts);
memset (fh->free_bitmap, 0xff, vec_len (fh->free_bitmap) * sizeof (uword));
/* Clear any extraneous set bits */
set_bits = vec_len (fh->free_bitmap) * BITS (uword);
for (i = max_elts; i < set_bits; i++)
fh->free_bitmap = clib_bitmap_set (fh->free_bitmap, i, 0);
这个时候才申请空闲块位图所需要的内存,并初始化成都空闲。注意,空闲块的数目有可能不是32或64的整数,这个时候要将超出部分恢复成0值。
/* Create the initial free vector */
for (i = 0; i < max_elts; i++)
fi[i] = (max_elts - 1) - i;
*pool_ptr = v;
初始化空闲内存块编号向量,即所有内存块当前都空闲。
这里有一个小细节,空闲内存块编号在向量中降序排列,这样做有一个好处,在bitmap将高位bit清0后,bitmap的len有机会自动减小。