定义
/* /lib/librte_mempool/rte_mempool_ops.c */
struct rte_mempool_ops_table rte_mempool_ops_table = {
.sl = RTE_SPINLOCK_INITIALIZER,
.num_ops = 0
};
/* lib/librte_mempool/rte_mempool.h*/
struct rte_mempool_ops_table {
rte_spinlock_t sl; /**< Spinlock for add/delete. */
uint32_t num_ops; /**< Number of used ops structs in the table. */
/**
* Storage for all possible ops structs.
*/
struct rte_mempool_ops ops[RTE_MEMPOOL_MAX_OPS_IDX];
} __rte_cache_aligned;
rte_mempool_ops_table 作为全局变量,内部ops数组存储已注册的ops信息,ops包括操作内存池的一系列(alloc、free、dequeue、enqueue)函数指针。每个进程内部都有存储 ops 数组,这样mempool 可以在主进程和辅助进程之间共享(自己未这样使用过)。访问ops 数组的索引在进程之间是有效的,但是mempool结构里直接存储的函数指针,在进程间未必是有效的。这就导致我们在mempool结构体内有个"ops_index" 的变量。
ops数组的初始化
/* /drivers/mempool/ring/rte_mempool_ring.c */
MEMPOOL_REGISTER_OPS(ops_mp_mc);
MEMPOOL_REGISTER_OPS(ops_sp_sc);
MEMPOOL_REGISTER_OPS(ops_mp_sc);
MEMPOOL_REGISTER_OPS(ops_sp_mc);
MEMPOOL_REGISTER_OPS(ops_mt_rts);
MEMPOOL_REGISTER_OPS(ops_mt_hts);
static const struct rte_mempool_ops ops_mp_mc = {
.name = "ring_mp_mc",
.alloc = common_ring_alloc,
.free = common_ring_free,
.enqueue = common_ring_mp_enqueue,
.dequeue = common_ring_mc_dequeue,
.get_count = common_ring_get_count,
};
/* /lib/librte_mempool/rte_mempool.h */
#define MEMPOOL_REGISTER_OPS(ops) \
RTE_INIT(mp_hdlr_init_##ops) \
{ \
rte_mempool_register_ops(&ops); \
}
通过宏定义和 ops_mp_mc 的定义,在程序main函数执行前完成ops数组的初始化。
如何设置mempool结构体内的“ops_index”
rte_mempool_create 的最后一个变量flag,可设置内存池操作方式是否支持多 producer 和 多 consumer。未主动设置情况下,支持多 producer 和 多 consumer 。如此能确定 ops_index 对应 “ring_mp_mc” 的ops数组元素的下标。
int
rte_mempool_set_ops_byname(struct rte_mempool *mp, const char *name,
void *pool_config)
{
struct rte_mempool_ops *ops = NULL;
unsigned i;
/* too late, the mempool is already populated. */
if (mp->flags & MEMPOOL_F_POOL_CREATED)
return -EEXIST;
for (i = 0; i < rte_mempool_ops_table.num_ops; i++) {
if (!strcmp(name,
rte_mempool_ops_table.ops[i].name)) {
ops = &rte_mempool_ops_table.ops[i];
break;
}
}
if (ops == NULL)
return -EINVAL;
mp->ops_index = i;
mp->pool_config = pool_config;
rte_mempool_trace_set_ops_byname(mp, name, pool_config);
return 0;
}