dpdk中要使用timer 必须分为下面三步
第一步:在dpdk中要使用timer,必须初始化RTE timer library
其源码分析如下:
void
rte_timer_subsystem_init(void)
{
unsigned lcore_id;
/* since priv_timer is static, it's zeroed by default, so only init some
* fields.
*/
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++) {
rte_spinlock_init(&priv_timer[lcore_id].list_lock);
priv_timer[lcore_id].prev_lcore = lcore_id;
}
}
可见time子系统初始化是给每一个cpu初始化一个spin lock,并记录当前的cpu id
第二步:必须为每个timer的回调函数初始化一个rte_timer结构体
void
rte_timer_init(struct rte_timer *tim)
{
union rte_timer_status status;
status.state = RTE_TIMER_STOP;
status.owner = RTE_TIMER_NO_OWNER;
tim->status.u32 = status.u32;
}
可以看到只是初始化rte_timer的status 变量
第三步:设置timer工作的模式
int
rte_timer_reset(struct rte_timer *tim, uint64_t ticks,
enum rte_timer_type type, unsigned tim_lcore,
rte_timer_cb_t fct, void *arg)
{
#得到当前时间
uint64_t cur_time = rte_get_timer_cycles();
uint64_t period;
if (unlikely((tim_lcore != (unsigned)LCORE_ID_ANY) &&
!(rte_lcore_is_enabled(tim_lcore) ||
rte_lcore_has_role(tim_lcore, ROLE_SERVICE) == 0)))
return -1;
#如果type是PERIODICAL,说明是周期timer,这里就要设置timer的周期,否则周期就是零
if (type == PERIODICAL)
period = ticks;
else
period = 0;
#获得当前时间和周期后继续设置timer
return __rte_timer_reset(tim, cur_time + ticks, period, tim_lcore,
fct, arg, 0);
}
static int
__rte_timer_reset(struct rte_timer *tim, uint64_t expire,
uint64_t period, unsigned tim_lcore,
rte_timer_cb_t fct, void *arg,
int local_is_locked)
{
union rte_timer_status prev_status, status;
int ret;
#获得当前cpu id
unsigned lcore_id = rte_lcore_id();
/* round robin for tim_lcore */
#这里检查timer是否可以建立在其他core上
if (tim_lcore == (unsigned)LCORE_ID_ANY) {
if (lcore_id < RTE_MAX_LCORE) {
/* EAL thread with valid lcore_id */
tim_lcore = rte_get_next_lcore(
priv_timer[lcore_id].prev_lcore,
0, 1);
priv_timer[lcore_id].prev_lcore = tim_lcore;
} else
/* non-EAL thread do not run rte_timer_manage(),
* so schedule the timer on the first enabled lcore. */
tim_lcore = rte_get_next_lcore(LCORE_ID_ANY, 0, 1);
}
/* wait that the timer is in correct status before update,
* and mark it as being configured */
#只是timer状态
ret = timer_set_config_state(tim, &prev_status);
if (ret < 0)
return -1;
#用于debug函数,release版本为空函数
__TIMER_STAT_ADD(reset, 1);
#如果timer已经在运行状态说明这次是要update状态
if (prev_status.state == RTE_TIMER_RUNNING &&
lcore_id < RTE_MAX_LCORE) {
priv_timer[lcore_id].updated = 1;
}
/* remove it from list */
#如果timer是pending的,则调用timer_del删除timer
if (prev_status.state == RTE_TIMER_PENDING) {
timer_del(tim, prev_status, local_is_locked);
__TIMER_STAT_ADD(pending, -1);
}
#设置time的周期,下次到期时间,回调函数,以及参数
tim->period = period;
tim->expire = expire;
tim->f = fct;
tim->arg = arg;
#debug函数,打印状态
__TIMER_STAT_ADD(pending, 1);
#添加这个timer后,这个timer就开始正常工作了
timer_add(tim, tim_lcore, local_is_locked);
/* update state: as we are in CONFIG state, only us can modify
* the state so we don't need to use cmpset() here */
rte_wmb();
status.state = RTE_TIMER_PENDING;
status.owner = (int16_t)tim_lcore;
tim->status.u32 = status.u32;
return 0;
}