LINUX时钟系列-04-从CPU主频到系统时间
首先我们从一个实验开始:
#define _GNU_SOURCE
#include <sched.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
// gcc -o rdtsc rdtsc.c -lpthread -std=c99
uint64_t get_tsc()
{
uint64_t a, d;
__asm__ volatile("rdtsc" : "=a"(a), "=d"(d));
return (d << 32) | a;
}
void bind_cpu(int cpuid)
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpuid, &cpuset);
pthread_t tid = pthread_self();
pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset);
}
#define CPU_NUM 16
uint64_t cpuid_tsc[CPU_NUM];
int epoch = 0;
void* thread_func(void* arg)
{
int cpuid = *((int*)arg);
bind_cpu(cpuid);
int old = epoch;
while(1)
{
if (old == epoch)
continue;
old = epoch;
uint64_t tsc = get_tsc();
uint64_t diff = tsc - cpuid_tsc[cpuid];
printf("cpuid=%2d, tsc=%llu, diff=%llu\n", cpuid, tsc, diff);
cpuid_tsc[cpuid] = tsc;
}
return NULL;
}
int main()
{
// 启动线程
int cpuids[CPU_NUM];
for (int i = 0; i < CPU_NUM; ++i)
{
pthread_t tid;
cpuids[i] = i;
pthread_create(&tid, NULL, thread_func, &cpuids[i]);
}
// 初始化tsc
sleep(1);
for (int i = 0; i < CPU_NUM; ++i)
cpuid_tsc[i] = get_tsc();
// 测试
while(1)
{
sleep(1);
printf("\n");
++epoch;
}
return 0;
}
先在一个16核的机器上运行一下:

运行结果如下:


再换一台72核的机器:

运行结果如下:


观察这两台机器的运行结果,我们发现了三点:
1.绑定在不同CPU核心上的程序,同一时刻读取到的tsc的值都差不多(即使他们位于两颗CPU上!)
2.tsc的值基本上按照CPU的标称频率增加
3.tsc的值跟机器的启动时间有关(uptime)