获取机器当前CPU频率

该博客介绍了一个在Linux环境下,通过读取MSR寄存器和使用`perf_cpu_info`结构体来获取CPU当前频率的方法。涉及到的关键函数包括`native_read_tsc`、`calibrate_tsc`、`aperfmperf_mhz`和`aperf_get_min_freq_mhz`,通过多线程计算所有CPU核心的最小频率。

                                         获取机器当前CPU频率

struct perf_cpu_info
{
    int tsc;
    int index;
    int mhz;
};
struct perf_cpu_info *cpu_list;

static unsigned long long native_read_tsc(void)
{
    unsigned long long val;
    asm volatile("rdtsc": "=A" (val));
    return val;
}

unsigned int calibrate_tsc(void)
{
    unsigned long long val;
    unsigned long long val2;
    long long diff = 0;
    int error = 0,cnt = 0;
    unsigned long long min_tsc = (unsigned long long) -1;
    val = native_read_tsc();
    do {
        usleep(4950);
        val2 =native_read_tsc();
        diff = val2 - val;
        if (diff > 0) {
            min_tsc = min_tsc > diff?diff:min_tsc;
            error = 0;
            cnt ++;
        }
        if (error ++ > 6) return -1;
        val = val2;
    } while(cnt < 3);

    return min_tsc / 5;
}

int aperfmperf_mhz(unsigned int cpu, unsigned int tsc)
{
    unsigned long long aperf = 0, aperf2 = 0;
    unsigned long long mperf = 0, mperf2 = 0;

    if (rdmsr_on_cpu(MSR_IA32_MPERF, cpu, &mperf) != 0)
        return -1;

    if (rdmsr_on_cpu(MSR_IA32_APERF, cpu, &aperf) != 0)
        return -1;
    usleep(99950);
    if (rdmsr_on_cpu(MSR_IA32_MPERF, cpu, &mperf2) != 0)
        return -1;

    if (rdmsr_on_cpu(MSR_IA32_APERF, cpu, &aperf2) != 0)
        return -1;

    aperf = aperf2 - aperf;
    mperf = mperf2 - mperf;
    return tsc * aperf / mperf / 1000;
}

void* threadFun(void* arg)  //arg  传递线程标号(自己定义)
{
    cpu_set_t mask;  //CPU核的集合
    cpu_set_t get;   //获取在集合中的CPU
    struct perf_cpu_info *perf = (struct perf_cpu_info *)arg;

    CPU_ZERO(&mask);
    CPU_SET(perf->index, &mask);
    if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
    {
         printf("warning: could not set CPU affinity, continuing...\n");
    }
    perf->mhz = aperfmperf_mhz(perf->index, perf->tsc);
//    printf("cpu[%d] %d Mhz\n", perf->index, perf->mhz);

    return NULL;
}

int aperf_get_min_freq_mhz(int tsc)
{
    int num=0;
    int i;

    num = sysconf(_SC_NPROCESSORS_CONF);  //获取核数
    pthread_t thread[num];

    cpu_list = (struct perf_cpu_info*)malloc(num * sizeof (struct perf_cpu_info));
    for(i=0;i<num;i++)
    {
        cpu_list[i].tsc = tsc;
        cpu_list[i].index = i;
        pthread_create(&thread[i],NULL,threadFun,(void*)&cpu_list[i]);
    }
    unsigned int min = (unsigned int)(-1);
    for(i=0; i< num; i++)
    {
        pthread_join(thread[i],NULL);//等待所有的线程结束,线程为死循环所以CTRL+C结束
    }
    for(i=0; i< num; i++)
    {
        min = cpu_list[i].mhz < min ? cpu_list[i].mhz : min;
    }

    free(cpu_list);
    return min;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值