dpdk中的timer

dpdk 中有提供time没看负责定时操作,同时在example/timer中有提供一个测试code
可以告知大家如何使用time 没看
从meson.build中可以看出源文件只有一个main.c
deps += 'timer'
sources = files(
	'main.c'
)
从makefile中可以看出binary的名字叫timer,这个main.c 可以同时被build 为动态链接库和静态链接库
# binary name
APP = timer

# all source are stored in SRCS-y
SRCS-y := main.c

# Build using pkg-config variables if possible
$(shell pkg-config --exists libdpdk)
ifeq ($(.SHELLSTATUS),0)

all: shared
.PHONY: shared static
shared: build/$(APP)-shared
	ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
	ln -sf $(APP)-static build/$(APP)

CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
与此同时可以看到优化级别是O3
timer的入口函数为main函数
int
main(int argc, char **argv)
{
	int ret;
	uint64_t hz;
	unsigned lcore_id;

	/* init EAL */
	#初始化running time 环境
	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_panic("Cannot init EAL\n");

	#由于我们是测试timer,因此要用到rte提供的time子系统
	/* init RTE timer library */
	rte_timer_subsystem_init();

	/* init timer structures */
	#初始化两个timer的回调函数
	rte_timer_init(&timer0);
	rte_timer_init(&timer1);

	/* load timer0, every second, on master lcore, reloaded automatically */
	#timer 0在主核上(本例中是当前cpu),不一定是cpu0,自动状态
	hz = rte_get_timer_hz();
	#获取当前cpu
	lcore_id = rte_lcore_id();
	#设置timer运行的模式,例如这里就是周期运行PERIODICAL,周期是1s
	rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);

	/* load timer1, every second/3, on next lcore, reloaded manually */
	#timer1 在主cpu的下一个cpu上,如果主cpu 是0 的话,则下一个cpu可能是1
	lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
	#设置timer运行的模式,例如这里就是单次运行,如果要周期运行的话,需要在timer1的回调函数中继续调用rte_timer_reset
	#设置timer,运行周期是0.33s
	rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);

	/* call lcore_mainloop() on every slave lcore */
	#再出了当前cpu上外的cpu上跑lcore_mainloop
	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
		rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);
	}

	/* call it on master lcore too */
	#在当前cpu上跑
	(void) lcore_mainloop(NULL);

	return 0;
}

static void
timer0_cb(__attribute__((unused)) struct rte_timer *tim,
	  __attribute__((unused)) void *arg)
{
	static unsigned counter = 0;
	unsigned lcore_id = rte_lcore_id();

	printf("%s() on lcore %u\n", __func__, lcore_id);

	/* this timer is automatically reloaded until we decide to
	 * stop it, when counter reaches 20. */
	if ((counter ++) == 20)
		rte_timer_stop(tim);
}
我们看一下timer0_cb的实现,运行20次就到期了,每次一秒的话,则20s后这个timer就停止了
我们看看lcore_mainloop的实现,如上所示每个cpu上都会跑一个lcore_mainloop
static __attribute__((noreturn)) int
lcore_mainloop(__attribute__((unused)) void *arg)
{
	uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
	unsigned lcore_id;

	lcore_id = rte_lcore_id();
	printf("Starting mainloop on core %u\n", lcore_id);

	while (1) {
		/*
		 * Call the timer handler on each core: as we don't
		 * need a very precise timer, so only call
		 * rte_timer_manage() every ~10ms (at 2Ghz). In a real
		 * application, this will enhance performances as
		 * reading the HPET timer is not efficient.
		 */
		cur_tsc = rte_rdtsc();
		diff_tsc = cur_tsc - prev_tsc;
		#从这里知道dpdk中通过rte_timer_manage来管理当前core上的定时器,并且定时器的分辨率是TIMER_RESOLUTION_CYCLES
		if (diff_tsc > TIMER_RESOLUTION_CYCLES) {
			rte_timer_manage();
			prev_tsc = cur_tsc;
		}
	}
}

你可能感兴趣的:(dpdk源码分析)