Linux之用户态 读取cntvct_el0 值

一、使用ARMv8提供的独立定时器CNTVCT_EL0

System counter是Arm64下独立于CPU core的计数器,在系统上电时,会给此计数器设置固定的频率。一个映射System counter计数器内容的寄存器为CNTVCT_EL0,可在用户态下读取此寄存器获取counter值。而CNTFRQ_EL0保存的是counter的频率值(详细内容参考《【ARMv8】通用定时器总结》)。通过下面的函数实现获取counter值及频率值:

static inline uint64_t 
arm64_cntvct(void) 
{   
    uint64_t tsc;   
    asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));   
    return tsc; 

static inline uint64_t 
arm64_cntfrq(void)
{   
    uint64_t freq;   
    asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));   
    return freq; 

static inline uint64_t 
rdtsc(void) 
{
    return arm64_cntvct();
}

 arm64_cntvct 这个函数需要进行换算的,读取寄存器 cntvct_el0,只是获取了固定频率下的寄存器的值,这个值仅仅是单调自增,代表“晶振”几次,并不是生活中时间单位秒 或者ns;

代码修改如下:

 uint64_t gettscns() {
    uint64_t io_tsc_ns;
    uint64_t tsc;
    __asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (tsc));
    io_tsc_ns = tsc * 32;
    return io_tsc_ns;
}

  io_tsc_ns = tsc * 32; 读出的值,需要在换算成ns; 

那么 32是怎么获取的?

通过 dmesg |grep clock ,获取时钟的分辨率,即晶振一次多长时间;

通过上面的截图,可以看到 resolution 32 ns,就是这个分辨率。

对于这个时间的获取和换算,分析结束;

使用方式;

int main ()

{    

     start = gettscns();
     syscall(SYS_clock_gettime, CLOCK_REALTIME, &sys);
     stop = gettscns();

     printf("tsc: %ld ns ,stop - start);

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值