#define _GNU_SOURCE#include #include #include #include #include #include #include #include #include #define CPU_MASK 0static inline uint64_t arm64_pmccntr(void){ uint64_t tsc; asm volatile("mrs %0, pmccntr_el0" : "=r"(tsc)); return tsc;}static inline uint64_t rdtsc(void){ return arm64_pmccntr();}// 进程亲和-OK#if 0void cpu_affinty_set(void){ cpu_set_t mask; //CPU掩码 CPU_ZERO(&mask); //初始化set集,将set置为空 CPU_SET(CPU_MASK, &mask); //将本进程绑定到CPU0上 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno)); }}int main(void){cpu_affinty_set();while (1){uint64_t val = rdtsc();printf("rdtsc:%lu\n", val);usleep(1000);}}#endif// 使用线程方式绑定核0static int app_set_affinity(int coreid){cpu_set_t cpuset;CPU_ZERO(&cpuset);CPU_SET(coreid, &cpuset);return pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);}static void* get_cycle_loop(void *arg){if (app_set_affinity(0)){perror("app_set_affinity failed");}while (1){uint64_t val = rdtsc();printf("rdtsc:%lu\n", val);usleep(1000);}}int main(void){pthread_t tid;if (pthread_create(&tid, NULL, get_cycle_loop, NULL)){perror("pthread_create failed");}while (1){sleep(10);}}
a. 在多核系统中,每个CPU有自己独立的PMU寄存器,并且每个CPU的cycle值是不一样的,所以在获取cycle值时,前后应该位于同一个线程,该线程需要亲和到某个CPU上;
b. 如果将使能代码段放于内核代码块时,需要注意enable_pmu_pmccntr接口调用位置,应该在内核完全启动后进行调用,例如在start_kernel调用时,只使能了主核的cycle获取功能,当应用层将线程绑定到其他核时,获取cycle值出现指令非法问题;
https://ilinuxkernel.com/?p=1755