diff --git a/src/arm/freq.c b/src/arm/freq.c new file mode 100644 index 0000000..c5214a1 --- /dev/null +++ b/src/arm/freq.c @@ -0,0 +1,47 @@ +#include + +#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 + } +} diff --git a/src/arm/freq.h b/src/arm/freq.h new file mode 100644 index 0000000..660cbb4 --- /dev/null +++ b/src/arm/freq.h @@ -0,0 +1,6 @@ +#ifndef __FREQ__ +#define __FREQ__ + +void nop_function_arm(uint64_t iters); + +#endif diff --git a/src/arm/midr.c b/src/arm/midr.c index 805ec47..32d5151 100644 --- a/src/arm/midr.c +++ b/src/arm/midr.c @@ -14,6 +14,7 @@ #include "../common/global.h" #include "../common/soc.h" +#include "../common/freq.h" #include "udev.h" #include "midr.h" #include "uarch.h" @@ -41,6 +42,12 @@ struct frequency* get_frequency_info(uint32_t core) { freq->base = UNKNOWN_DATA; 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; } diff --git a/src/common/freq.c b/src/common/freq.c index 8c972d4..a5914b9 100644 --- a/src/common/freq.c +++ b/src/common/freq.c @@ -2,11 +2,6 @@ #define _GNU_SOURCE -// TODO: This should be under common/ -#include "../x86/apic.h" -#include "../x86/freq/freq.h" -#include "global.h" - #include #include #include @@ -17,6 +12,14 @@ #include #include +#ifdef ARCH_X86 + #include "../x86/freq/freq.h" +#elif ARCH_ARM + #include "../arm/freq.h" +#endif + +#include "global.h" + static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, 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 // whereas measure_max_frequency uses nop instructions. This makes the former // x86 dependant whereas the latter is architecture independant. -int64_t measure_max_frequency(void) { - // TODO: Support binding on all cores inside a SoC (x86 - // hybrid topologies and ARM SoCs) - int core = 0; +int64_t measure_max_frequency(uint32_t core) { if (!bind_to_cpu(core)) { printErr("Failed binding the process to CPU %d", core); return -1; diff --git a/src/common/freq.h b/src/common/freq.h index 10923ec..0eb42ab 100644 --- a/src/common/freq.h +++ b/src/common/freq.h @@ -1,6 +1,6 @@ #ifndef __COMMON_FREQ__ #define __COMMON_FREQ__ -int64_t measure_max_frequency(void); +int64_t measure_max_frequency(uint32_t core); #endif diff --git a/src/common/global.c b/src/common/global.c index 1b1b87d..96c91af 100644 --- a/src/common/global.c +++ b/src/common/global.c @@ -1,3 +1,14 @@ +#ifdef _WIN32 + #define NOMINMAX + #include +#elif defined __linux__ + #define _GNU_SOURCE + #include +#elif defined __FreeBSD__ + #include + #include +#endif + #include #include #include @@ -199,6 +210,34 @@ void* erealloc(void *ptr, size_t size) { 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(¤tCPU); + CPU_SET(cpu_id, ¤tCPU); + if (sched_setaffinity (0, sizeof(currentCPU), ¤tCPU) == -1) { + printWarn("sched_setaffinity: %s", strerror(errno)); + return false; + } + return true; + #elif defined __FreeBSD__ + cpuset_t currentCPU; + CPU_ZERO(¤tCPU); + CPU_SET(cpu_id, ¤tCPU); + if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), ¤tCPU) == -1) { + printWarn("cpuset_setaffinity: %s", strerror(errno)); + return false; + } + return true; + #endif +} +#endif + void print_version(FILE *restrict stream) { #ifdef GIT_FULL_VERSION fprintf(stream, "cpufetch %s (%s %s)\n", GIT_FULL_VERSION, OS_STR, ARCH_STR); diff --git a/src/common/global.h b/src/common/global.h index 69ead1d..8e333fc 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -19,6 +19,9 @@ char *strremove(char *str, const char *sub); void* emalloc(size_t size); void* ecalloc(size_t nmemb, 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); #endif diff --git a/src/x86/apic.c b/src/x86/apic.c index 1757110..745aad9 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,14 +1,3 @@ -#ifdef _WIN32 - #define NOMINMAX - #include -#elif defined __linux__ - #define _GNU_SOURCE - #include -#elif defined __FreeBSD__ - #include - #include -#endif - #include #include #include @@ -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(¤tCPU); - CPU_SET(cpu_id, ¤tCPU); - if (sched_setaffinity (0, sizeof(currentCPU), ¤tCPU) == -1) { - printWarn("sched_setaffinity: %s", strerror(errno)); - return false; - } - return true; - #elif defined __FreeBSD__ - cpuset_t currentCPU; - CPU_ZERO(¤tCPU); - CPU_SET(cpu_id, ¤tCPU); - if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), ¤tCPU) == -1) { - printWarn("cpuset_setaffinity: %s", strerror(errno)); - return false; - } - return true; - #endif -} -#endif - #ifdef __linux__ int get_total_cores_module(int total_cores, int module) { int total_modules = 2; diff --git a/src/x86/apic.h b/src/x86/apic.h index 0f79995..c104ea5 100644 --- a/src/x86/apic.h +++ b/src/x86/apic.h @@ -17,10 +17,6 @@ struct apic { bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo); uint32_t is_smt_enabled_amd(struct topology* topo); -#ifndef __APPLE__ -bool bind_to_cpu(int cpu_id); -#endif - #ifdef __linux__ int get_total_cores_module(int total_cores, int module); #endif diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 25b31ae..1b00207 100644 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -967,7 +967,8 @@ struct frequency* get_frequency_info(struct cpuInfo* cpu) { #ifdef __linux__ if (freq->max == UNKNOWN_DATA) { printWarn("All previous methods failed, measuring CPU frequency"); - freq->max = measure_max_frequency(); + // TODO: Support hybrid architectures + freq->max = measure_max_frequency(0); } #endif