[v1.05] Add support for frequency measurement in ARM (had to move bind_to_cpu to common dir)

This commit is contained in:
Dr-Noob
2024-02-16 23:37:37 +01:00
parent 72eee0e08e
commit d71a461d83
10 changed files with 114 additions and 54 deletions

47
src/arm/freq.c Normal file
View File

@@ -0,0 +1,47 @@
#include <stdint.h>
#define INSERT_ASM_ONCE __asm volatile("nop");
#define INSERT_ASM_10_TIMES \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
#define INSERT_ASM_100_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES
#define INSERT_ASM_1000_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
void nop_function_arm(uint64_t iters) {
for (uint64_t i = 0; i < iters; i++) {
INSERT_ASM_1000_TIMES
INSERT_ASM_1000_TIMES
INSERT_ASM_1000_TIMES
INSERT_ASM_1000_TIMES
}
}

6
src/arm/freq.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef __FREQ__
#define __FREQ__
void nop_function_arm(uint64_t iters);
#endif

View File

@@ -14,6 +14,7 @@
#include "../common/global.h" #include "../common/global.h"
#include "../common/soc.h" #include "../common/soc.h"
#include "../common/freq.h"
#include "udev.h" #include "udev.h"
#include "midr.h" #include "midr.h"
#include "uarch.h" #include "uarch.h"
@@ -41,6 +42,12 @@ struct frequency* get_frequency_info(uint32_t core) {
freq->base = UNKNOWN_DATA; freq->base = UNKNOWN_DATA;
freq->max = get_max_freq_from_file(core); freq->max = get_max_freq_from_file(core);
#ifdef __linux__
if (freq->max == UNKNOWN_DATA) {
printWarn("Unable to find max frequency from udev, measuring CPU frequency");
freq->max = measure_max_frequency(core);
}
#endif
return freq; return freq;
} }

View File

@@ -2,11 +2,6 @@
#define _GNU_SOURCE #define _GNU_SOURCE
// TODO: This should be under common/
#include "../x86/apic.h"
#include "../x86/freq/freq.h"
#include "global.h"
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@@ -17,6 +12,14 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#ifdef ARCH_X86
#include "../x86/freq/freq.h"
#elif ARCH_ARM
#include "../arm/freq.h"
#endif
#include "global.h"
static long static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid, perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags) { int cpu, int group_fd, unsigned long flags) {
@@ -36,10 +39,7 @@ perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
// - measure_frequency uses actual computation while measuring the frequency // - measure_frequency uses actual computation while measuring the frequency
// whereas measure_max_frequency uses nop instructions. This makes the former // whereas measure_max_frequency uses nop instructions. This makes the former
// x86 dependant whereas the latter is architecture independant. // x86 dependant whereas the latter is architecture independant.
int64_t measure_max_frequency(void) { int64_t measure_max_frequency(uint32_t core) {
// TODO: Support binding on all cores inside a SoC (x86
// hybrid topologies and ARM SoCs)
int core = 0;
if (!bind_to_cpu(core)) { if (!bind_to_cpu(core)) {
printErr("Failed binding the process to CPU %d", core); printErr("Failed binding the process to CPU %d", core);
return -1; return -1;

View File

@@ -1,6 +1,6 @@
#ifndef __COMMON_FREQ__ #ifndef __COMMON_FREQ__
#define __COMMON_FREQ__ #define __COMMON_FREQ__
int64_t measure_max_frequency(void); int64_t measure_max_frequency(uint32_t core);
#endif #endif

View File

@@ -1,3 +1,14 @@
#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#elif defined __linux__
#define _GNU_SOURCE
#include <sched.h>
#elif defined __FreeBSD__
#include <sys/param.h>
#include <sys/cpuset.h>
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -199,6 +210,34 @@ void* erealloc(void *ptr, size_t size) {
return newptr; return newptr;
} }
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id) {
#ifdef _WIN32
HANDLE process = GetCurrentProcess();
DWORD_PTR processAffinityMask = 1 << cpu_id;
return SetProcessAffinityMask(process, processAffinityMask);
#elif defined __linux__
cpu_set_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if (sched_setaffinity (0, sizeof(currentCPU), &currentCPU) == -1) {
printWarn("sched_setaffinity: %s", strerror(errno));
return false;
}
return true;
#elif defined __FreeBSD__
cpuset_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), &currentCPU) == -1) {
printWarn("cpuset_setaffinity: %s", strerror(errno));
return false;
}
return true;
#endif
}
#endif
void print_version(FILE *restrict stream) { void print_version(FILE *restrict stream) {
#ifdef GIT_FULL_VERSION #ifdef GIT_FULL_VERSION
fprintf(stream, "cpufetch %s (%s %s)\n", GIT_FULL_VERSION, OS_STR, ARCH_STR); fprintf(stream, "cpufetch %s (%s %s)\n", GIT_FULL_VERSION, OS_STR, ARCH_STR);

View File

@@ -19,6 +19,9 @@ char *strremove(char *str, const char *sub);
void* emalloc(size_t size); void* emalloc(size_t size);
void* ecalloc(size_t nmemb, size_t size); void* ecalloc(size_t nmemb, size_t size);
void* erealloc(void *ptr, size_t size); void* erealloc(void *ptr, size_t size);
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id);
#endif
void print_version(FILE *restrict stream); void print_version(FILE *restrict stream);
#endif #endif

View File

@@ -1,14 +1,3 @@
#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#elif defined __linux__
#define _GNU_SOURCE
#include <sched.h>
#elif defined __FreeBSD__
#include <sys/param.h>
#include <sys/cpuset.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -72,34 +61,6 @@ uint32_t get_apic_id(bool x2apic_id) {
} }
} }
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id) {
#ifdef _WIN32
HANDLE process = GetCurrentProcess();
DWORD_PTR processAffinityMask = 1 << cpu_id;
return SetProcessAffinityMask(process, processAffinityMask);
#elif defined __linux__
cpu_set_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if (sched_setaffinity (0, sizeof(currentCPU), &currentCPU) == -1) {
printWarn("sched_setaffinity: %s", strerror(errno));
return false;
}
return true;
#elif defined __FreeBSD__
cpuset_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), &currentCPU) == -1) {
printWarn("cpuset_setaffinity: %s", strerror(errno));
return false;
}
return true;
#endif
}
#endif
#ifdef __linux__ #ifdef __linux__
int get_total_cores_module(int total_cores, int module) { int get_total_cores_module(int total_cores, int module) {
int total_modules = 2; int total_modules = 2;

View File

@@ -17,10 +17,6 @@ struct apic {
bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo); bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo);
uint32_t is_smt_enabled_amd(struct topology* topo); uint32_t is_smt_enabled_amd(struct topology* topo);
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id);
#endif
#ifdef __linux__ #ifdef __linux__
int get_total_cores_module(int total_cores, int module); int get_total_cores_module(int total_cores, int module);
#endif #endif

View File

@@ -967,7 +967,8 @@ struct frequency* get_frequency_info(struct cpuInfo* cpu) {
#ifdef __linux__ #ifdef __linux__
if (freq->max == UNKNOWN_DATA) { if (freq->max == UNKNOWN_DATA) {
printWarn("All previous methods failed, measuring CPU frequency"); printWarn("All previous methods failed, measuring CPU frequency");
freq->max = measure_max_frequency(); // TODO: Support hybrid architectures
freq->max = measure_max_frequency(0);
} }
#endif #endif