dpdk-22.07.0-trace机制简析

trace定义

以rte_eal_trace_thread_remote_launch函数为例

RTE_TRACE_POINT(
	rte_eal_trace_thread_remote_launch,
	RTE_TRACE_POINT_ARGS(int (*f)(void *), void *arg,
		unsigned int worker_id, int rc),
	rte_trace_point_emit_ptr(f);
	rte_trace_point_emit_ptr(arg);
	rte_trace_point_emit_u32(worker_id);
	rte_trace_point_emit_int(rc);
)

#define RTE_TRACE_POINT(tp, args, ...) \
	__RTE_TRACE_POINT(generic, tp, args, __VA_ARGS__)

#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \
extern rte_trace_point_t __##_tp; \
static __rte_always_inline void \
_tp _args \
{ \
	__rte_trace_point_emit_header_##_mode(&__##_tp); \
	__VA_ARGS__ \
}
最终宏展开为:
extern uint64_t __rte_eal_trace_thread_remote_launch;

static __rte_always_inline void rte_eal_trace_thread_remote_launch(int (*f)(void *), void *arg, unsigned int slave_id, int rc) {
    __rte_trace_point_emit_header_generic(&__rte_eal_trace_thread_remote_launch);
	rte_trace_point_emit_ptr(f);
	rte_trace_point_emit_ptr(arg);
	rte_trace_point_emit_u32(slave_id);
	rte_trace_point_emit_int(rc);
}

trace注册

RTE_TRACE_POINT_REGISTER(rte_eal_trace_thread_remote_launch,
	lib.eal.thread.remote.launch)
#define RTE_TRACE_POINT_REGISTER(trace, name) \
rte_trace_point_t __attribute__((section("__rte_trace_point"))) __##trace; \
RTE_INIT(trace##_init) \
{ \
	__rte_trace_point_register(&__##trace, RTE_STR(name), \
		(void (*)(void)) trace); \
}

#define RTE_INIT(func) \
	RTE_INIT_PRIO(func, LAST)

#ifndef RTE_INIT_PRIO /* Allow to override from EAL */
#define RTE_INIT_PRIO(func, prio) \
static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)
#endif

其中:
gcc允许为函数设置__attribute__ ((constructor))和__attribute__ ((destructor))两种属性,顾名思义,就是将被修饰的函数作为构造函数或析构函数。程序员可以通过类似下面的方式为函数设置这些属性:
void funcBeforeMain() attribute ((constructor));
void funcAfterMain() attribute ((destructor));
也可以放在函数名之前:
void attribute ((constructor)) funcBeforeMain();
void attribute ((destructor)) funcAfterMain();
带有(constructor)属性的函数将在main()函数之前被执行,而带有(destructor)属性的函数将在main()退出时执行。

表示 func 这个函数会在 main 之前执行,RTE_PRIO(prio) 是优先级,used 表示这个函数即使未被使用也不优化。

trace使能

rte_eal_init->eal_log_level_parse->eal_parse_common_option进行argc和argv参数解析
在eal_options.h头文件中定义了各个参数的枚举,trace有关的枚举为OPT_TRACE_NUM(使能trace)、OPT_TRACE_DIR_NUM(设置trace文件存放目录)
在eal_trace_init->trace_mkdir函数中会创建存放trace文件的子目录
最终写文件的时机:
rte_eal_cleanup->rte_trace_save
当函数运行完后在rte_trace_save函数中会将本进程的trace信息写入文件中

trace使用

以examples\helloworld为例
在examples\helloworld\main.c中添加rte_trace_pattern使能lib.eal.thread.remote.launc函数

...
rte_trace_pattern("lib.eal.thread.remote.launch",true);
...
rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int worker_id)
{
	int rc = -EBUSY;

	/* Check if the worker is in 'WAIT' state. Use acquire order
	 * since 'state' variable is used as the guard variable.
	 */
	if (__atomic_load_n(&lcore_config[worker_id].state,
			__ATOMIC_ACQUIRE) != WAIT)
		goto finish;

	lcore_config[worker_id].arg = arg;
	/* Ensure that all the memory operations are completed
	 * before the worker thread starts running the function.
	 * Use worker thread function as the guard variable.
	 */
	__atomic_store_n(&lcore_config[worker_id].f, f, __ATOMIC_RELEASE);

	eal_thread_wake_worker(worker_id);	//此处执行回调函数f
	rc = 0;

finish:
	rte_eal_trace_thread_remote_launch(f, arg, worker_id, rc);
	return rc;
}

当函数执行rte_eal_trace_thread_remote_launch时会依次rte_trace_point_emit_XXX等操作
其中会运行mem = __rte_trace_mem_get(val);此函数表示获取当前trace写入内存的位置。

#define rte_trace_point_emit_u64(in) __rte_trace_point_emit(in, uint64_t)
#define rte_trace_point_emit_i64(in) __rte_trace_point_emit(in, int64_t)
#define rte_trace_point_emit_u32(in) __rte_trace_point_emit(in, uint32_t)
#define rte_trace_point_emit_i32(in) __rte_trace_point_emit(in, int32_t)
#define rte_trace_point_emit_u16(in) __rte_trace_point_emit(in, uint16_t)
#define rte_trace_point_emit_i16(in) __rte_trace_point_emit(in, int16_t)
#define rte_trace_point_emit_u8(in) __rte_trace_point_emit(in, uint8_t)
#define rte_trace_point_emit_i8(in) __rte_trace_point_emit(in, int8_t)
#define rte_trace_point_emit_int(in) __rte_trace_point_emit(in, int32_t)
#define rte_trace_point_emit_long(in) __rte_trace_point_emit(in, long)
#define rte_trace_point_emit_size_t(in) __rte_trace_point_emit(in, size_t)
#define rte_trace_point_emit_float(in) __rte_trace_point_emit(in, float)
#define rte_trace_point_emit_double(in) __rte_trace_point_emit(in, double)
#define rte_trace_point_emit_ptr(in) __rte_trace_point_emit(in, uintptr_t)


#define __rte_trace_point_emit(in, type) \
do { \
	memcpy(mem, &(in), sizeof(in)); \
	mem = RTE_PTR_ADD(mem, sizeof(in)); \
} while (0)
#define RTE_PTR_ADD(ptr, x) ((void*)((uintptr_t)(ptr) + (x)))

会将此片内存中的值写入到缓存中,等最终调用rte_trace_save函数时再将内存中的值写入文件中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值