目录
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