目录
概述
dpdk19.01提供了qsbr模式的rcu库,其具体实现在lib/librte_rcu
目录中。librte_rcu
是无锁线程安全的,这个库提供了读者报告静默状态的能力,让写者知道读者是否进入过静默状态。
dpdk中QSBR具体实现是通过一个struct rte_rcu_qsbr_cnt
变量qs,将多个线程共享的内存管理起来。总体思路是通过比较线程的静默期版本号与qs全局版本号的大小,判断是否所有线程进入过本次静默期。
使用librte_rcu
进行内存释放的线程的基本步骤如下:
- 解除内存的引用
- 调用
rte_rcu_qsbr_start()
函数将全局版本号加1,触发所有读线程报告静默状态 - 调用
rte_rcu_qsbr_check()
遍历检查所有读者线程,确保都进入过本次静默期 - 释放内存
初始化
初始化时,会用到一些通过的工具宏,定义在在dpdk-master/lib/librte_eal/common/include/rte_common.h
中。如下:
#define RTE_CACHE_LINE_SIZE 64
#define RTE_ALIGN_MUL_CEIL(v, mul) \
((v + 64 - 1)/64) * 64 // (64地板除 + 1)*64
#define RTE_ALIGN_FLOOR(val, 64) \
val & (~(64 - 1)) // 64的地板除
#define RTE_ALIGN_CEIL(val, 64) \
RTE_ALIGN_FLOOR(val + 64 - 1, 64) // 64的地板除 + 1
#define RTE_ALIGN(val, align) RTE_ALIGN_CEIL(val, align) // 64的地板除 + 1
在dpdk-master\lib\librte_rcu\rte_rcu_qsbr.h
中,定义了初始化时用到的一些函数与宏。
/* 工作线程计数器 */
struct rte_rcu_qsbr_cnt {
uint64_t cnt; // 静默态计数器,0表示下线。使用64bits,防止计数溢出
uint32_t lock_cnt; // counter锁, 用于CONFIG_RTE_LIBRTE_RCU_DEBUG
} __rte_cache_aligned;
#define __RTE_QSBR_THRID_ARRAY_ELM_SIZE (sizeof(uint64_t) * 8) // 数组元素大小为64 B
#define __RTE_QSBR_THRID_ARRAY_SIZE(max_threads)\
RTE_ALIGN(RTE_ALIGN_MUL_CEIL(max_threads, 64) >> 3, RTE_CACHE_LINE_SIZE) // 计算得到线程数组的大小
/*
* (struct rte_rcu_qsbr_cnt *)(v + 1): 获得 v中 rte_rcu_qsbr_cnt 的地址偏移,此时指针p变为 struct rte_rcu_qsbr_cnt *类型
* + v->max_threads: 得到 v中thread id_array的偏移,
* + i
*/
#define __RTE_QSBR_THRID_ARRAY_ELM(v, i) // 获得线程数组的第 i 个
((uint6