欢迎来到 DPDK交流社区 ,有什么问题可以尽管在这里提问,您将会收到社区其他成员的回答;也可以将您的总结写在这里,为社区其他成员提供帮助。 (QQ交流群:127163755)

使用rte_power提供的接口改变CPU频率后,会影响rte_rdtsc和rte_get_tsc_hz么?

1个回答

+1 投票

static inline uint64_t
rte_rdtsc(void)
{
    union {
        uint64_t tsc_64;
        struct {
            uint32_t lo_32;
            uint32_t hi_32;
        };
    } tsc;

#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
    if (unlikely(rte_cycles_vmware_tsc_map)) {
        /* ecx = 0x10000 corresponds to the physical TSC for VMware */
        asm volatile("rdpmc" :
                     "=a" (tsc.lo_32),
                     "=d" (tsc.hi_32) :
                     "c"(0x10000));
        return tsc.tsc_64;
    }
#endif

    asm volatile("rdtsc" :
             "=a" (tsc.lo_32),
             "=d" (tsc.hi_32));
    return tsc.tsc_64;
}

首先是上面的获取时间的代码,它读取的是系统寄存器的值,这个值每次cpu circle一次的时候值被统计到 EDX:EAX中,当cpu频率改变以后相应的circle减少这个时候读取到的hz数相应降低,对于时间计算来说是没有什么影响的。改变的只是rte_rdtsc和rte_get_tsc_hz这两个函数返回的值。

具体请参考:

64-ia-32-architectures-software-developer-manual-325462.pdf

https://www.cs.uaf.edu/2011/fall/cs301/intel_x64_megadoc_2011.pdf

http://en.wikipedia.org/wiki/Time_Stamp_Counter

http://www.cnblogs.com/cnmaizi/archive/2011/01/17/1937772.html

 

最新回答 4月 22, 2015 用户: oops (2,160 分)
随着cpu频率的改变,rte_rdtsc会改变是无容置疑的;但是在1.7.1版本里rte_get_tsc_hz只是返回一个全局变量eal_tsc_resolution_hz,而通过rte_power_set_freq设置cpu频率时并没有改变全局变量eal_tsc_resolution_hz。
这个地方得到的值只是在CPU频率改变以后获取到的,以后就不会再变的。他是在初始化的时候就确定了的。
那么问题来了:
CPU频率改变了,每秒的TSC值也就不再恒定了,而rte_get_tsc_hz却是恒定的,通过这两者相除得到的时间单位(秒)难道还能准确吗?
这他是有先后顺序的,摘录一段l3fwd-power的代码可以参考一下
        /* init power management library */
        ret = rte_power_init(lcore_id);
        if (ret)
            rte_exit(EXIT_FAILURE, "Power management library "
                "initialization failed on core%u\n", lcore_id);

        /* init timer structures for each enabled lcore */
        rte_timer_init(&power_timers[lcore_id]);
        hz = rte_get_timer_hz();
        rte_timer_reset(&power_timers[lcore_id],
            hz/TIMER_NUMBER_PER_SECOND, SINGLE, lcore_id,
                        power_timer_cb, NULL);
代码中首先是需要设定频率,然后在获取rte_get_tsc_hz值,所以这个地方以后再重新设定频率的话,这个地方需要重新执行一遍才对吧。
这段代码是用来初始化rte定时器的,你所说的在设定频率后需要重新reset定时器是对的。但是如果rte_get_tsc_hz获得的还是旧值,以此值来reset定时器还是不对。

我觉得需要在设定频率的接口里把eal_tsc_resolution_hz更新,以便rte_get_tsc_hz能正确返回实际的频率。
eal_tsc_resolution_hz这个值在单独使用时确实需要更新,但是在实际使用的时候大部分时候都在用rte_rdtsc()函数获取当前的系统时间的。eal_tsc_resolution_hz值做微调,像上面那个例子一样,在timer rest时直接还是取用了一下rte_get_timer_cycles函数的值,rte_get_tsc_cycles(void) { return rte_rdtsc(); } 这样就是当前的时间了。
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)))
        return -1;

    if (type == PERIODICAL)
        period = ticks;
    else
        period = 0;

    return __rte_timer_reset(tim,  cur_time + ticks, period, tim_lcore,
              fct, arg, 0);
}

个人愚见,若有错误还请多多指教。丰富论坛内容,多谢!
...