替换x86 rdtsc汇编指令
现象描述
编译报错:error: impossible constraint in ‘asm’
__asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi));。
问题原因
TSC是时间戳计数器的缩写,它是Pentium兼容处理器中的一个计数器,它记录自启动以来处理器消耗的时钟周期数。在每个时钟到来时,该计数器自动加一。因为TSC随着处理器周期速率的变化而变化,所以它提供了非常高的精确度。它经常被用来分析和检测代码。x86平台TSC的值可以通过rdtsc指令来读取,鲲鹏平台需要使用类似算法实现。
处理步骤
x86平台实现样例:
static inline uint64_t Rdtsc()
{
uint32_t lo, hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (uint64_t)hi << 32 | lo;
}
鲲鹏平台实现样例:
- 方法一:使用Linux提供的获取时间函数clock_gettime进行近似替换。
#include <time.h> static inline uint64_t Rdtsc() { struct timespec tmp; clock_gettime(CLOCK_MONOTONIC, &tmp); return tmp.tv_sec*2400000000+(uint64_t)tmp.tv_nsec*2.4; //2400000000和2.4基于服务器主频而定 }
- 方法二:鲲鹏有Performance Monitors Control Register系列寄存器,其中PMCCNTR_EL0就类似于x86的TSC寄存器。但默认情况用户态是不可读的,需要
内核态 使能后才能读取。请参见GitHub网站编译内核模块,开启对系统寄存器的访问。- 下载源码。
git clone https://github.com/jerinjacobk/armv8_pmu_cycle_counter_el0
- 执行make命令。
- 执行insmod pmu_el0_cycle_counter.ko命令安装内核模块,使能内核态(初次执行即可)。
- 代码替换。
static inline uint64_t read_pmccntr(void) { uint64_t val; asm volatile("mrs %0, pmccntr_el0" : "=r"(val)); return val; }
- 下载源码。
父主题: 嵌入式汇编类问题