Release 0.2.1 with expanded hardware detection
This commit is contained in:
@@ -10,7 +10,8 @@ LDLIBS ?= -lm $(TLS_LDLIBS)
|
|||||||
PTHREAD := -pthread
|
PTHREAD := -pthread
|
||||||
|
|
||||||
DIST := dist
|
DIST := dist
|
||||||
DRIVER := src/main.c src/app/benchmark.c
|
DRIVER := src/main.c src/app/benchmark.c src/app/hw_detect.c
|
||||||
|
DRIVER_DEPS := src/app/benchmark.h src/app/hw_detect.h src/app/upload.c
|
||||||
ASM_ARM64 := src/kernels/fossbench-arm64.S
|
ASM_ARM64 := src/kernels/fossbench-arm64.S
|
||||||
ASM_AMD64 := src/kernels/fossbench-amd64.S
|
ASM_AMD64 := src/kernels/fossbench-amd64.S
|
||||||
ASM_I386 := src/kernels/fossbench-i386.S
|
ASM_I386 := src/kernels/fossbench-i386.S
|
||||||
@@ -117,41 +118,41 @@ macos-amd64: $(DIST)/fossbench-macos-amd64
|
|||||||
windows-amd64: $(DIST)/fossbench-windows-amd64.exe
|
windows-amd64: $(DIST)/fossbench-windows-amd64.exe
|
||||||
windows-i386: $(DIST)/fossbench-windows-i386.exe
|
windows-i386: $(DIST)/fossbench-windows-i386.exe
|
||||||
|
|
||||||
$(DIST)/fossbench-linux-arm64: $(DRIVER) $(ASM_ARM64) | $(DIST)
|
$(DIST)/fossbench-linux-arm64: $(DRIVER) $(DRIVER_DEPS) $(ASM_ARM64) | $(DIST)
|
||||||
$(CC_ARM64) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_ARM64) $(LDLIBS)
|
$(CC_ARM64) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_ARM64) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-linux-amd64: $(DRIVER) $(ASM_AMD64) | $(DIST)
|
$(DIST)/fossbench-linux-amd64: $(DRIVER) $(DRIVER_DEPS) $(ASM_AMD64) | $(DIST)
|
||||||
$(CC_AMD64) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_AMD64) $(LDLIBS)
|
$(CC_AMD64) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_AMD64) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-linux-i386: $(DRIVER) $(ASM_I386) | $(DIST)
|
$(DIST)/fossbench-linux-i386: $(DRIVER) $(DRIVER_DEPS) $(ASM_I386) | $(DIST)
|
||||||
$(CC_I386) -m32 -march=pentium4 -fno-pie -no-pie $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_I386) $(LDLIBS)
|
$(CC_I386) -m32 -march=pentium4 -fno-pie -no-pie $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_I386) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-linux-ppc32be: $(DRIVER) $(ASM_PPC32) | $(DIST)
|
$(DIST)/fossbench-linux-ppc32be: $(DRIVER) $(DRIVER_DEPS) $(ASM_PPC32) | $(DIST)
|
||||||
$(CC_PPC32BE) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_PPC32) $(LDLIBS)
|
$(CC_PPC32BE) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_PPC32) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-linux-ppc64be: $(DRIVER) $(ASM_PPC64) | $(DIST)
|
$(DIST)/fossbench-linux-ppc64be: $(DRIVER) $(DRIVER_DEPS) $(ASM_PPC64) | $(DIST)
|
||||||
$(CC_PPC64BE) -mcpu=970 -maltivec $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_PPC64) $(LDLIBS)
|
$(CC_PPC64BE) -mcpu=970 -maltivec $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_PPC64) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-macos-arm64: $(DRIVER) $(ASM_ARM64) | $(DIST)
|
$(DIST)/fossbench-macos-arm64: $(DRIVER) $(DRIVER_DEPS) $(ASM_ARM64) | $(DIST)
|
||||||
$(CC_MACOS_ARM64) -arch arm64 $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_ARM64) $(LDLIBS)
|
$(CC_MACOS_ARM64) -arch arm64 $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(ASM_ARM64) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-macos-amd64: $(DRIVER) $(ASM_AMD64) | $(DIST)
|
$(DIST)/fossbench-macos-amd64: $(DRIVER) $(DRIVER_DEPS) $(ASM_AMD64) | $(DIST)
|
||||||
MACOSX_DEPLOYMENT_TARGET=$(MACOS_AMD64_MIN) $(CC_MACOS_AMD64) -arch x86_64 -mmacosx-version-min=$(MACOS_AMD64_MIN) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -Wl,-no_fixup_chains -o $@ $(DRIVER) $(ASM_AMD64) $(LDLIBS)
|
MACOSX_DEPLOYMENT_TARGET=$(MACOS_AMD64_MIN) $(CC_MACOS_AMD64) -arch x86_64 -mmacosx-version-min=$(MACOS_AMD64_MIN) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -Wl,-no_fixup_chains -o $@ $(DRIVER) $(ASM_AMD64) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
# Windows builds are static and use WinHTTP.
|
# Windows builds are static and use WinHTTP.
|
||||||
$(DIST)/fossbench-windows-amd64.exe: $(DRIVER) $(ASM_AMD64) | $(DIST)
|
$(DIST)/fossbench-windows-amd64.exe: $(DRIVER) $(DRIVER_DEPS) $(ASM_AMD64) | $(DIST)
|
||||||
$(CC_WINDOWS_AMD64) $(CFLAGS) $(PTHREAD) -static -o $@ $(DRIVER) $(ASM_AMD64) -lm -lwinhttp
|
$(CC_WINDOWS_AMD64) $(CFLAGS) $(PTHREAD) -static -o $@ $(DRIVER) $(ASM_AMD64) -lm -lwinhttp -ladvapi32
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
$(DIST)/fossbench-windows-i386.exe: $(DRIVER) $(ASM_I386) | $(DIST)
|
$(DIST)/fossbench-windows-i386.exe: $(DRIVER) $(DRIVER_DEPS) $(ASM_I386) | $(DIST)
|
||||||
$(CC_WINDOWS_I386) -march=pentium4 $(CFLAGS) $(PTHREAD) -static -o $@ $(DRIVER) $(ASM_I386) -lm -lwinhttp
|
$(CC_WINDOWS_I386) -march=pentium4 $(CFLAGS) $(PTHREAD) -static -o $@ $(DRIVER) $(ASM_I386) -lm -lwinhttp -ladvapi32
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
|
|
||||||
# Add a native rule if one was not already made above.
|
# Add a native rule if one was not already made above.
|
||||||
@@ -177,7 +178,7 @@ ifeq ($(OSNAME)-$(HOST_ARCHNAME),macos-amd64)
|
|||||||
NATIVE_HAS_RULE := yes
|
NATIVE_HAS_RULE := yes
|
||||||
endif
|
endif
|
||||||
ifneq ($(NATIVE_HAS_RULE),yes)
|
ifneq ($(NATIVE_HAS_RULE),yes)
|
||||||
$(NATIVE_BIN): $(DRIVER) $(HOST_KERNEL) | $(DIST)
|
$(NATIVE_BIN): $(DRIVER) $(DRIVER_DEPS) $(HOST_KERNEL) | $(DIST)
|
||||||
$(CC) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(HOST_KERNEL) $(LDLIBS)
|
$(CC) $(CFLAGS) $(TLS_CFLAGS) $(PTHREAD) $(LDFLAGS) -o $@ $(DRIVER) $(HOST_KERNEL) $(LDLIBS)
|
||||||
@echo "built $@"
|
@echo "built $@"
|
||||||
endif
|
endif
|
||||||
|
|||||||
+5
-242
@@ -8,16 +8,13 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "benchmark.h"
|
#include "benchmark.h"
|
||||||
|
#include "hw_detect.h"
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
# include <sys/utsname.h>
|
|
||||||
#endif
|
|
||||||
#if !defined(_WIN32) && !defined(FB_NO_UPLOAD)
|
#if !defined(_WIN32) && !defined(FB_NO_UPLOAD)
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
@@ -28,59 +25,37 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/sysctl.h>
|
|
||||||
# include <mach/mach_time.h>
|
# include <mach/mach_time.h>
|
||||||
# include <mach/mach.h>
|
# include <mach/mach.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32) && (defined(__i386__) || defined(__x86_64__))
|
|
||||||
# include <cpuid.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The server URL can be changed when building. */
|
/* The server URL can be changed when building. */
|
||||||
#ifndef FB_API_BASE_URL
|
#ifndef FB_API_BASE_URL
|
||||||
# define FB_API_BASE_URL "https://fossbench.net"
|
# define FB_API_BASE_URL "https://fossbench.net"
|
||||||
#endif
|
#endif
|
||||||
#define FB_VERSION "0.2.0"
|
#define FB_VERSION "0.2.1"
|
||||||
|
|
||||||
/* Names used in the header. */
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# define FB_OS "Windows"
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
# define FB_OS "macOS"
|
|
||||||
#elif defined(__linux__)
|
|
||||||
# define FB_OS "Linux"
|
|
||||||
#else
|
|
||||||
# define FB_OS "POSIX"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
# define FB_ARCH "ARM64"
|
|
||||||
# define D_INT "64-bit ALU: madd, umulh, udiv, bitops"
|
# define D_INT "64-bit ALU: madd, umulh, udiv, bitops"
|
||||||
# define D_FP "double: fmadd, fdiv, fsqrt"
|
# define D_FP "double: fmadd, fdiv, fsqrt"
|
||||||
# define D_SIMD "NEON ASIMD: 128-bit integer + float"
|
# define D_SIMD "NEON ASIMD: 128-bit integer + float"
|
||||||
#elif defined(__x86_64__) || defined(_M_X64)
|
#elif defined(__x86_64__) || defined(_M_X64)
|
||||||
# define FB_ARCH "x86-64"
|
|
||||||
# define D_INT "64-bit ALU: imul, mul, div, bitops"
|
# define D_INT "64-bit ALU: imul, mul, div, bitops"
|
||||||
# define D_FP "double: mulsd/addsd, divsd, sqrtsd"
|
# define D_FP "double: mulsd/addsd, divsd, sqrtsd"
|
||||||
# define D_SIMD "SSE2: 128-bit integer + float"
|
# define D_SIMD "SSE2: 128-bit integer + float"
|
||||||
#elif defined(__i386__) || defined(_M_IX86)
|
#elif defined(__i386__) || defined(_M_IX86)
|
||||||
# define FB_ARCH "x86 32-bit"
|
|
||||||
# define D_INT "Pentium 4 integer ALU and software 64-bit arithmetic"
|
# define D_INT "Pentium 4 integer ALU and software 64-bit arithmetic"
|
||||||
# define D_FP "x87 scalar double-precision floating point"
|
# define D_FP "x87 scalar double-precision floating point"
|
||||||
# define D_SIMD "SSE2: 128-bit integer vectors"
|
# define D_SIMD "SSE2: 128-bit integer vectors"
|
||||||
#elif defined(__powerpc64__)
|
#elif defined(__powerpc64__)
|
||||||
# define FB_ARCH "PowerPC 64-bit big-endian"
|
|
||||||
# define D_INT "64-bit PowerPC integer ALU"
|
# define D_INT "64-bit PowerPC integer ALU"
|
||||||
# define D_FP "PowerPC scalar double-precision floating point"
|
# define D_FP "PowerPC scalar double-precision floating point"
|
||||||
# define D_SIMD "AltiVec: 128-bit integer vectors (PowerPC 970)"
|
# define D_SIMD "AltiVec: 128-bit integer vectors (PowerPC 970)"
|
||||||
#elif defined(__powerpc__)
|
#elif defined(__powerpc__)
|
||||||
# define FB_ARCH "PowerPC 32-bit big-endian"
|
|
||||||
# define D_INT "PPC32 integer ALU and software 64-bit arithmetic"
|
# define D_INT "PPC32 integer ALU and software 64-bit arithmetic"
|
||||||
# define D_FP "PowerPC scalar double-precision floating point"
|
# define D_FP "PowerPC scalar double-precision floating point"
|
||||||
# define D_SIMD "runtime-selected PS, VSX, AltiVec, or scalar"
|
# define D_SIMD "runtime-selected PS, VSX, AltiVec, or scalar"
|
||||||
#else
|
#else
|
||||||
# define FB_ARCH "unknown"
|
|
||||||
# define D_INT "64-bit integer ALU"
|
# define D_INT "64-bit integer ALU"
|
||||||
# define D_FP "double-precision FP"
|
# define D_FP "double-precision FP"
|
||||||
# define D_SIMD "128-bit SIMD: integer + float"
|
# define D_SIMD "128-bit SIMD: integer + float"
|
||||||
@@ -354,209 +329,6 @@ static uint8_t *g_simd_src; /* pristine NEON seed, copied per-core. */
|
|||||||
static double *g_bodies_src; /* pristine initial conditions. */
|
static double *g_bodies_src; /* pristine initial conditions. */
|
||||||
static uint32_t *g_sort_src; /* pristine unsorted data. */
|
static uint32_t *g_sort_src; /* pristine unsorted data. */
|
||||||
|
|
||||||
struct system_info {
|
|
||||||
char cpu[256];
|
|
||||||
char model[256];
|
|
||||||
char operating_system[256];
|
|
||||||
char compiler[128];
|
|
||||||
char kernel[128];
|
|
||||||
long cpu_cores;
|
|
||||||
long cpu_threads;
|
|
||||||
long memory_mb;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void trim(char *s)
|
|
||||||
{
|
|
||||||
char *p = s;
|
|
||||||
size_t n;
|
|
||||||
while (isspace((unsigned char)*p)) p++;
|
|
||||||
if (p != s) memmove(s, p, strlen(p) + 1);
|
|
||||||
n = strlen(s);
|
|
||||||
while (n && isspace((unsigned char)s[n - 1])) s[--n] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the first device tree value. */
|
|
||||||
static int read_first_property(const char *path, char *dst, size_t cap)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
size_t n, i;
|
|
||||||
|
|
||||||
if (cap == 0)
|
|
||||||
return 0;
|
|
||||||
f = fopen(path, "rb");
|
|
||||||
if (f == NULL)
|
|
||||||
return 0;
|
|
||||||
n = fread(dst, 1, cap - 1, f);
|
|
||||||
fclose(f);
|
|
||||||
for (i = 0; i < n && dst[i] != '\0' && dst[i] != '\n' && dst[i] != '\r'; i++)
|
|
||||||
if ((unsigned char)dst[i] < 0x20)
|
|
||||||
dst[i] = ' ';
|
|
||||||
dst[i] = '\0';
|
|
||||||
trim(dst);
|
|
||||||
return dst[0] != '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static void detect_system_info(struct system_info *info)
|
|
||||||
{
|
|
||||||
#if defined(__linux__)
|
|
||||||
char cpuinfo_hardware[sizeof info->model] = "";
|
|
||||||
#endif
|
|
||||||
memset(info, 0, sizeof(*info));
|
|
||||||
info->cpu_threads = g_ncores;
|
|
||||||
info->cpu_cores = g_ncores;
|
|
||||||
strncpy(info->cpu, FB_ARCH, sizeof(info->cpu) - 1);
|
|
||||||
strncpy(info->operating_system, FB_OS, sizeof(info->operating_system) - 1);
|
|
||||||
#if defined(__clang__)
|
|
||||||
snprintf(info->compiler, sizeof(info->compiler), "Clang %s", __clang_version__);
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
snprintf(info->compiler, sizeof(info->compiler), "GCC %s", __VERSION__);
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
snprintf(info->compiler, sizeof(info->compiler), "MSVC %d", _MSC_VER);
|
|
||||||
#else
|
|
||||||
strncpy(info->compiler, "Unknown", sizeof(info->compiler) - 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
{
|
|
||||||
struct utsname u;
|
|
||||||
if (uname(&u) == 0)
|
|
||||||
snprintf(info->kernel, sizeof(info->kernel), "%s %s", u.sysname, u.release);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
static const char *const model_paths[] = {
|
|
||||||
"/sys/firmware/devicetree/base/compatible",
|
|
||||||
"/sys/firmware/devicetree/base/model",
|
|
||||||
"/proc/device-tree/compatible"
|
|
||||||
};
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < sizeof model_paths / sizeof model_paths[0]; i++)
|
|
||||||
if (read_first_property(model_paths[i], info->model,
|
|
||||||
sizeof info->model))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
FILE *f = fopen("/proc/cpuinfo", "r");
|
|
||||||
char line[512];
|
|
||||||
int pairs[1024][2], npairs = 0, physical = -1, core = -1;
|
|
||||||
if (f) {
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
|
||||||
char *colon = strchr(line, ':');
|
|
||||||
if (!colon) continue;
|
|
||||||
*colon++ = '\0'; trim(line); trim(colon);
|
|
||||||
if ((!strcmp(line, "model name") || !strcmp(line, "Processor") ||
|
|
||||||
!strcmp(line, "cpu")) && info->cpu[0] && !strcmp(info->cpu, FB_ARCH))
|
|
||||||
strncpy(info->cpu, colon, sizeof(info->cpu) - 1);
|
|
||||||
else if (!strcmp(line, "Hardware") && cpuinfo_hardware[0] == '\0')
|
|
||||||
strncpy(cpuinfo_hardware, colon, sizeof cpuinfo_hardware - 1);
|
|
||||||
else if (!strcmp(line, "physical id")) physical = atoi(colon);
|
|
||||||
else if (!strcmp(line, "core id")) core = atoi(colon);
|
|
||||||
if (physical >= 0 && core >= 0) {
|
|
||||||
int i, seen = 0;
|
|
||||||
for (i = 0; i < npairs; i++)
|
|
||||||
if (pairs[i][0] == physical && pairs[i][1] == core) seen = 1;
|
|
||||||
if (!seen && npairs < 1024) { pairs[npairs][0] = physical; pairs[npairs++][1] = core; }
|
|
||||||
physical = core = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
if (npairs > 0) info->cpu_cores = npairs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Try the system files if CPU info is missing. */
|
|
||||||
#if defined(__aarch64__) || defined(__arm__)
|
|
||||||
if (info->model[0] == '\0')
|
|
||||||
read_first_property("/sys/class/dmi/id/product_name", info->model,
|
|
||||||
sizeof info->model);
|
|
||||||
#endif
|
|
||||||
if (info->model[0] == '\0' && cpuinfo_hardware[0] != '\0')
|
|
||||||
snprintf(info->model, sizeof info->model, "%s", cpuinfo_hardware);
|
|
||||||
{
|
|
||||||
FILE *f = fopen("/proc/meminfo", "r");
|
|
||||||
char line[256]; long kb;
|
|
||||||
if (f) {
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
|
||||||
if (sscanf(line, "MemTotal: %ld kB", &kb) == 1) {
|
|
||||||
info->memory_mb = kb / 1024;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
FILE *f = fopen("/etc/os-release", "r"); char line[512];
|
|
||||||
if (f) { while (fgets(line, sizeof(line), f)) if (!strncmp(line, "PRETTY_NAME=", 12)) {
|
|
||||||
char *v = line + 12; trim(v);
|
|
||||||
if (v[0] == '\"') { memmove(v, v + 1, strlen(v)); if (strlen(v) && v[strlen(v)-1] == '\"') v[strlen(v)-1] = '\0'; }
|
|
||||||
snprintf(info->operating_system, sizeof(info->operating_system), "%s", v); break;
|
|
||||||
} fclose(f); }
|
|
||||||
}
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
{
|
|
||||||
size_t n = sizeof(info->cpu); uint64_t mem = 0; size_t mn = sizeof(mem);
|
|
||||||
size_t model_n = sizeof(info->model);
|
|
||||||
int cores = 0; size_t cn = sizeof(cores);
|
|
||||||
if (sysctlbyname("machdep.cpu.brand_string", info->cpu, &n, NULL, 0) != 0)
|
|
||||||
strncpy(info->cpu, FB_ARCH, sizeof info->cpu - 1);
|
|
||||||
sysctlbyname("hw.model", info->model, &model_n, NULL, 0);
|
|
||||||
if (sysctlbyname("hw.physicalcpu", &cores, &cn, NULL, 0) == 0) info->cpu_cores = cores;
|
|
||||||
if (sysctlbyname("hw.memsize", &mem, &mn, NULL, 0) == 0) info->memory_mb = (long)(mem / 1024 / 1024);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
char product[64] = ""; size_t pn = sizeof(product);
|
|
||||||
struct utsname u;
|
|
||||||
if (sysctlbyname("kern.osproductversion", product, &pn, NULL, 0) == 0)
|
|
||||||
snprintf(info->operating_system, sizeof(info->operating_system), "macOS %s", product);
|
|
||||||
if (uname(&u) == 0)
|
|
||||||
snprintf(info->kernel, sizeof(info->kernel), "%s %s", u.sysname, u.release);
|
|
||||||
}
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
{
|
|
||||||
MEMORYSTATUSEX ms;
|
|
||||||
ms.dwLength = sizeof(ms);
|
|
||||||
if (GlobalMemoryStatusEx(&ms))
|
|
||||||
info->memory_mb = (long)(ms.ullTotalPhys / 1024 / 1024);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
OSVERSIONINFOEXA version;
|
|
||||||
typedef LONG (WINAPI *rtl_get_version_fn)(OSVERSIONINFOEXA *);
|
|
||||||
rtl_get_version_fn rtl_get_version = (rtl_get_version_fn)(void *)
|
|
||||||
GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion");
|
|
||||||
memset(&version, 0, sizeof(version)); version.dwOSVersionInfoSize = sizeof(version);
|
|
||||||
if (rtl_get_version && rtl_get_version(&version) == 0) {
|
|
||||||
snprintf(info->operating_system, sizeof(info->operating_system),
|
|
||||||
"Windows %lu.%lu (build %lu)", (unsigned long)version.dwMajorVersion,
|
|
||||||
(unsigned long)version.dwMinorVersion, (unsigned long)version.dwBuildNumber);
|
|
||||||
snprintf(info->kernel, sizeof(info->kernel), "NT %lu.%lu build %lu",
|
|
||||||
(unsigned long)version.dwMajorVersion, (unsigned long)version.dwMinorVersion,
|
|
||||||
(unsigned long)version.dwBuildNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
|
||||||
{
|
|
||||||
/* Read the CPU name from CPUID. */
|
|
||||||
unsigned eax, ebx, ecx, edx, max_ext;
|
|
||||||
char brand[49];
|
|
||||||
int i;
|
|
||||||
__cpuid(0x80000000, eax, ebx, ecx, edx);
|
|
||||||
max_ext = eax;
|
|
||||||
if (max_ext >= 0x80000004) {
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
__cpuid(0x80000002u + (unsigned)i, eax, ebx, ecx, edx);
|
|
||||||
memcpy(brand + i * 16 + 0, &eax, 4);
|
|
||||||
memcpy(brand + i * 16 + 4, &ebx, 4);
|
|
||||||
memcpy(brand + i * 16 + 8, &ecx, 4);
|
|
||||||
memcpy(brand + i * 16 + 12, &edx, 4);
|
|
||||||
}
|
|
||||||
brand[48] = '\0';
|
|
||||||
trim(brand);
|
|
||||||
if (brand[0])
|
|
||||||
snprintf(info->cpu, sizeof(info->cpu), "%s", brand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Synthesise a compressible corpus. */
|
/* Synthesise a compressible corpus. */
|
||||||
static void build_corpus(uint8_t *buf, size_t len)
|
static void build_corpus(uint8_t *buf, size_t len)
|
||||||
@@ -972,7 +744,7 @@ static void print_header(const struct system_info *info)
|
|||||||
printf(" model: %s\n", info->model[0] ? info->model : "unknown");
|
printf(" model: %s\n", info->model[0] ? info->model : "unknown");
|
||||||
printf(" cores: %ld physical / %ld threads\n", info->cpu_cores, info->cpu_threads);
|
printf(" cores: %ld physical / %ld threads\n", info->cpu_cores, info->cpu_threads);
|
||||||
printf(" memory: %ld MB\n", info->memory_mb);
|
printf(" memory: %ld MB\n", info->memory_mb);
|
||||||
printf(" OS: %s (%s)\n", info->operating_system, FB_ARCH);
|
printf(" OS: %s (%s)\n", info->operating_system, hw_arch_name());
|
||||||
printf(" kernel: %s\n", info->kernel[0] ? info->kernel : "unknown");
|
printf(" kernel: %s\n", info->kernel[0] ? info->kernel : "unknown");
|
||||||
printf(" compiler: %s\n", info->compiler);
|
printf(" compiler: %s\n", info->compiler);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -993,17 +765,8 @@ int fossbench_run(int verbose, int upload_mode, int system_check)
|
|||||||
uint64_t duration_ms;
|
uint64_t duration_ms;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
{
|
hw_detect_system(&system_info);
|
||||||
#if defined(_WIN32)
|
g_ncores = system_info.cpu_threads;
|
||||||
SYSTEM_INFO si;
|
|
||||||
GetSystemInfo(&si);
|
|
||||||
long n = (long)si.dwNumberOfProcessors;
|
|
||||||
#else
|
|
||||||
long n = sysconf(_SC_NPROCESSORS_ONLN);
|
|
||||||
#endif
|
|
||||||
g_ncores = n > 0 ? n : 1;
|
|
||||||
}
|
|
||||||
detect_system_info(&system_info);
|
|
||||||
memset(&background, 0, sizeof(background));
|
memset(&background, 0, sizeof(background));
|
||||||
background.available_memory_mb = background.process_count = -1;
|
background.available_memory_mb = background.process_count = -1;
|
||||||
if (system_check) {
|
if (system_check) {
|
||||||
|
|||||||
@@ -0,0 +1,528 @@
|
|||||||
|
/* Platform-specific hardware and operating-system detection. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "hw_detect.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
# include <sys/utsname.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
# if defined(__i386__) || defined(__x86_64__)
|
||||||
|
# include <cpuid.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# define HW_OS "Windows"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# define HW_OS "macOS"
|
||||||
|
#elif defined(__linux__)
|
||||||
|
# define HW_OS "Linux"
|
||||||
|
#else
|
||||||
|
# define HW_OS "POSIX"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
# define HW_ARCH "ARM64"
|
||||||
|
#elif defined(__x86_64__) || defined(_M_X64)
|
||||||
|
# define HW_ARCH "x86-64"
|
||||||
|
#elif defined(__i386__) || defined(_M_IX86)
|
||||||
|
# define HW_ARCH "x86 32-bit"
|
||||||
|
#elif defined(__powerpc64__)
|
||||||
|
# define HW_ARCH "PowerPC 64-bit big-endian"
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
# define HW_ARCH "PowerPC 32-bit big-endian"
|
||||||
|
#else
|
||||||
|
# define HW_ARCH "unknown"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *hw_arch_name(void)
|
||||||
|
{
|
||||||
|
return HW_ARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trim(char *s)
|
||||||
|
{
|
||||||
|
char *p = s;
|
||||||
|
size_t n;
|
||||||
|
while (isspace((unsigned char)*p)) p++;
|
||||||
|
if (p != s) memmove(s, p, strlen(p) + 1);
|
||||||
|
n = strlen(s);
|
||||||
|
while (n && isspace((unsigned char)s[n - 1])) s[--n] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pull a marketing name such as "Apple M3 Max" out of platform metadata. */
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
static int apple_m_name(const char *text, char *dst, size_t cap)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
if (cap == 0 || text == NULL)
|
||||||
|
return 0;
|
||||||
|
for (p = text; *p; p++)
|
||||||
|
if ((p == text || !isalnum((unsigned char)p[-1])) &&
|
||||||
|
!strncmp(p, "Apple M", 7) && isdigit((unsigned char)p[7]))
|
||||||
|
break;
|
||||||
|
if (!*p)
|
||||||
|
return 0;
|
||||||
|
while (p[n] && n + 1 < cap &&
|
||||||
|
(isalnum((unsigned char)p[n]) || p[n] == ' ' || p[n] == '-'))
|
||||||
|
n++;
|
||||||
|
while (n && (p[n - 1] == ' ' || p[n - 1] == '-')) n--;
|
||||||
|
memcpy(dst, p, n);
|
||||||
|
dst[n] = '\0';
|
||||||
|
return n != 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Linux device trees identify Apple Silicon by its SoC code. */
|
||||||
|
#if defined(__linux__)
|
||||||
|
static int apple_m_name_from_soc(const char *text, char *dst, size_t cap)
|
||||||
|
{
|
||||||
|
static const struct { const char *soc, *name; } chips[] = {
|
||||||
|
{ "apple,t8103", "Apple M1" }, { "apple,t6000", "Apple M1 Pro" },
|
||||||
|
{ "apple,t6001", "Apple M1 Max" }, { "apple,t6002", "Apple M1 Ultra" },
|
||||||
|
{ "apple,t8112", "Apple M2" }, { "apple,t6020", "Apple M2 Pro" },
|
||||||
|
{ "apple,t6021", "Apple M2 Max" }, { "apple,t6022", "Apple M2 Ultra" },
|
||||||
|
{ "apple,t8122", "Apple M3" }, { "apple,t6031", "Apple M3 Pro" },
|
||||||
|
{ "apple,t6034", "Apple M3 Max" }, { "apple,t8132", "Apple M4" },
|
||||||
|
{ "apple,t6040", "Apple M4 Pro" }, { "apple,t6041", "Apple M4 Max" }
|
||||||
|
};
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if (apple_m_name(text, dst, cap)) return 1;
|
||||||
|
for (i = 0; i < sizeof chips / sizeof chips[0]; i++)
|
||||||
|
if (strstr(text, chips[i].soc)) {
|
||||||
|
snprintf(dst, cap, "%s", chips[i].name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__linux__) && (defined(__aarch64__) || defined(__arm__))
|
||||||
|
struct arm_cpu_name { unsigned char implementer; unsigned short part; const char *name; };
|
||||||
|
|
||||||
|
/* MIDR implementer and part numbers, kept in sync with Linux cputype.h. */
|
||||||
|
static const char *arm_core_name(unsigned implementer, unsigned part)
|
||||||
|
{
|
||||||
|
static const struct arm_cpu_name names[] = {
|
||||||
|
{0x41,0xC05,"Arm Cortex-A5"}, {0x41,0xC07,"Arm Cortex-A7"},
|
||||||
|
{0x41,0xC08,"Arm Cortex-A8"}, {0x41,0xC09,"Arm Cortex-A9"},
|
||||||
|
{0x41,0xC0D,"Arm Cortex-A12"}, {0x41,0xC0E,"Arm Cortex-A17"},
|
||||||
|
{0x41,0xC0F,"Arm Cortex-A15"}, {0x41,0xD03,"Arm Cortex-A53"},
|
||||||
|
{0x41,0xD04,"Arm Cortex-A35"}, {0x41,0xD05,"Arm Cortex-A55"},
|
||||||
|
{0x41,0xD07,"Arm Cortex-A57"}, {0x41,0xD08,"Arm Cortex-A72"},
|
||||||
|
{0x41,0xD09,"Arm Cortex-A73"}, {0x41,0xD0A,"Arm Cortex-A75"},
|
||||||
|
{0x41,0xD0B,"Arm Cortex-A76"}, {0x41,0xD0C,"Arm Neoverse N1"},
|
||||||
|
{0x41,0xD0D,"Arm Cortex-A77"}, {0x41,0xD0E,"Arm Cortex-A76AE"},
|
||||||
|
{0x41,0xD40,"Arm Neoverse V1"}, {0x41,0xD41,"Arm Cortex-A78"},
|
||||||
|
{0x41,0xD42,"Arm Cortex-A78AE"}, {0x41,0xD44,"Arm Cortex-X1"},
|
||||||
|
{0x41,0xD46,"Arm Cortex-A510"}, {0x41,0xD47,"Arm Cortex-A710"},
|
||||||
|
{0x41,0xD48,"Arm Cortex-X2"}, {0x41,0xD49,"Arm Neoverse N2"},
|
||||||
|
{0x41,0xD4B,"Arm Cortex-A78C"}, {0x41,0xD4C,"Arm Cortex-X1C"},
|
||||||
|
{0x41,0xD4D,"Arm Cortex-A715"}, {0x41,0xD4E,"Arm Cortex-X3"},
|
||||||
|
{0x41,0xD4F,"Arm Neoverse V2"}, {0x41,0xD80,"Arm Cortex-A520"},
|
||||||
|
{0x41,0xD81,"Arm Cortex-A720"}, {0x41,0xD82,"Arm Cortex-X4"},
|
||||||
|
{0x41,0xD83,"Arm Neoverse V3AE"}, {0x41,0xD84,"Arm Neoverse V3"},
|
||||||
|
{0x41,0xD85,"Arm Cortex-X925"}, {0x41,0xD87,"Arm Cortex-A725"},
|
||||||
|
{0x41,0xD89,"Arm Cortex-A720AE"}, {0x41,0xD8B,"Arm C1-Pro"},
|
||||||
|
{0x41,0xD8C,"Arm C1-Ultra"}, {0x41,0xD8E,"Arm Neoverse N3"},
|
||||||
|
{0x41,0xD90,"Arm C1-Premium"},
|
||||||
|
{0x42,0x100,"Broadcom Brahma-B53"}, {0x42,0x516,"Broadcom Vulcan"},
|
||||||
|
{0x43,0x0A1,"Cavium ThunderX"}, {0x43,0x0A2,"Cavium ThunderX 81xx"},
|
||||||
|
{0x43,0x0A3,"Cavium ThunderX 83xx"}, {0x43,0x0AF,"Cavium ThunderX2"},
|
||||||
|
{0x43,0x0B1,"Marvell Octeon TX2 98xx"}, {0x43,0x0B2,"Marvell Octeon TX2 96xx"},
|
||||||
|
{0x43,0x0B3,"Marvell Octeon TX2 95xx"}, {0x43,0x0B4,"Marvell Octeon TX2 95xxN"},
|
||||||
|
{0x43,0x0B5,"Marvell Octeon TX2 95xxMM"}, {0x43,0x0B6,"Marvell Octeon TX2 95xxO"},
|
||||||
|
{0x46,0x001,"Fujitsu A64FX"}, {0x48,0xD01,"HiSilicon TSV110"},
|
||||||
|
{0x48,0xD02,"HiSilicon HIP09"}, {0x48,0xD06,"HiSilicon HIP12"},
|
||||||
|
{0x4E,0x003,"NVIDIA Denver"}, {0x4E,0x004,"NVIDIA Carmel"},
|
||||||
|
{0x4E,0x010,"NVIDIA Olympus"}, {0x50,0x000,"APM X-Gene"},
|
||||||
|
{0x51,0x001,"Qualcomm Oryon"}, {0x51,0x200,"Qualcomm Kryo"},
|
||||||
|
{0x51,0x800,"Qualcomm Falkor / Kryo Gold"}, {0x51,0x801,"Qualcomm Kryo Silver"},
|
||||||
|
{0x51,0x802,"Qualcomm Kryo 3xx Gold"}, {0x51,0x803,"Qualcomm Kryo 3xx Silver"},
|
||||||
|
{0x51,0x804,"Qualcomm Kryo 4xx Gold"}, {0x51,0x805,"Qualcomm Kryo 4xx Silver"},
|
||||||
|
{0x51,0xC00,"Qualcomm Falkor"},
|
||||||
|
{0x61,0x022,"Apple M1 Icestorm"}, {0x61,0x023,"Apple M1 Firestorm"},
|
||||||
|
{0x61,0x024,"Apple M1 Pro Icestorm"}, {0x61,0x025,"Apple M1 Pro Firestorm"},
|
||||||
|
{0x61,0x028,"Apple M1 Max Icestorm"}, {0x61,0x029,"Apple M1 Max Firestorm"},
|
||||||
|
{0x61,0x032,"Apple M2 Blizzard"}, {0x61,0x033,"Apple M2 Avalanche"},
|
||||||
|
{0x61,0x034,"Apple M2 Pro Blizzard"}, {0x61,0x035,"Apple M2 Pro Avalanche"},
|
||||||
|
{0x61,0x038,"Apple M2 Max Blizzard"}, {0x61,0x039,"Apple M2 Max Avalanche"},
|
||||||
|
{0x6D,0xD49,"Microsoft Azure Cobalt 100"},
|
||||||
|
{0xC0,0xAC3,"Ampere-1"}, {0xC0,0xAC4,"Ampere-1A"}
|
||||||
|
};
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < sizeof names / sizeof names[0]; i++)
|
||||||
|
if (names[i].implementer == implementer && names[i].part == part)
|
||||||
|
return names[i].name;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *arm_implementer_name(unsigned implementer)
|
||||||
|
{
|
||||||
|
switch (implementer) {
|
||||||
|
case 0x41: return "Arm"; case 0x42: return "Broadcom";
|
||||||
|
case 0x43: return "Cavium/Marvell"; case 0x46: return "Fujitsu";
|
||||||
|
case 0x47: return "Google"; case 0x48: return "HiSilicon";
|
||||||
|
case 0x4D: return "Motorola/Freescale"; case 0x4E: return "NVIDIA";
|
||||||
|
case 0x50: return "APM"; case 0x51: return "Qualcomm";
|
||||||
|
case 0x53: return "Samsung"; case 0x56: return "Marvell";
|
||||||
|
case 0x61: return "Apple"; case 0x66: return "Faraday";
|
||||||
|
case 0x69: return "Intel"; case 0x6D: return "Microsoft";
|
||||||
|
case 0x70: return "Phytium"; case 0xC0: return "Ampere";
|
||||||
|
default: return "Unknown ARM vendor";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void format_arm_cores(char *dst, size_t cap,
|
||||||
|
const unsigned implementers[], const unsigned parts[], int count)
|
||||||
|
{
|
||||||
|
int i; size_t used = 0;
|
||||||
|
if (cap == 0) return;
|
||||||
|
dst[0] = '\0';
|
||||||
|
for (i = 0; i < count && used + 1 < cap; i++) {
|
||||||
|
const char *name = arm_core_name(implementers[i], parts[i]);
|
||||||
|
int n;
|
||||||
|
if (name)
|
||||||
|
n = snprintf(dst + used, cap - used, "%s%s", used ? " + " : "", name);
|
||||||
|
else
|
||||||
|
n = snprintf(dst + used, cap - used, "%s%s (MIDR 0x%02X/0x%03X)",
|
||||||
|
used ? " + " : "", arm_implementer_name(implementers[i]),
|
||||||
|
implementers[i], parts[i]);
|
||||||
|
if (n < 0 || (size_t)n >= cap - used) { dst[cap - 1] = '\0'; break; }
|
||||||
|
used += (size_t)n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *apple_m_name_from_midr(const unsigned implementers[],
|
||||||
|
const unsigned parts[], int count)
|
||||||
|
{
|
||||||
|
int i, generation = 0, tier = 0;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (implementers[i] != 0x61) return NULL;
|
||||||
|
switch (parts[i]) {
|
||||||
|
case 0x022: case 0x023: if (generation < 1) generation = 1; break;
|
||||||
|
case 0x024: case 0x025: generation = 1; if (tier < 1) tier = 1; break;
|
||||||
|
case 0x028: case 0x029: generation = 1; tier = 2; break;
|
||||||
|
case 0x032: case 0x033: if (generation < 2) generation = 2; break;
|
||||||
|
case 0x034: case 0x035: generation = 2; if (tier < 1) tier = 1; break;
|
||||||
|
case 0x038: case 0x039: generation = 2; tier = 2; break;
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (generation == 1) return tier == 2 ? "Apple M1 Max" : tier == 1 ? "Apple M1 Pro" : "Apple M1";
|
||||||
|
if (generation == 2) return tier == 2 ? "Apple M2 Max" : tier == 1 ? "Apple M2 Pro" : "Apple M2";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Read the first device tree value. */
|
||||||
|
static int read_first_property(const char *path, char *dst, size_t cap)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
size_t n, i;
|
||||||
|
|
||||||
|
if (cap == 0)
|
||||||
|
return 0;
|
||||||
|
f = fopen(path, "rb");
|
||||||
|
if (f == NULL)
|
||||||
|
return 0;
|
||||||
|
n = fread(dst, 1, cap - 1, f);
|
||||||
|
fclose(f);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if ((unsigned char)dst[i] < 0x20)
|
||||||
|
dst[i] = ' ';
|
||||||
|
dst[n] = '\0';
|
||||||
|
trim(dst);
|
||||||
|
return dst[0] != '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void hw_detect_system(struct system_info *info)
|
||||||
|
{
|
||||||
|
long detected_threads;
|
||||||
|
#if defined(__linux__)
|
||||||
|
char cpuinfo_hardware[sizeof info->model] = "";
|
||||||
|
char apple_soc[sizeof info->cpu] = "";
|
||||||
|
#if defined(__aarch64__) || defined(__arm__)
|
||||||
|
unsigned arm_implementers[32], arm_parts[32], arm_implementer = 0;
|
||||||
|
int arm_core_count = 0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32)
|
||||||
|
{
|
||||||
|
SYSTEM_INFO si;
|
||||||
|
GetSystemInfo(&si);
|
||||||
|
detected_threads = (long)si.dwNumberOfProcessors;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
detected_threads = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
#endif
|
||||||
|
if (detected_threads < 1) detected_threads = 1;
|
||||||
|
memset(info, 0, sizeof(*info));
|
||||||
|
info->cpu_threads = detected_threads;
|
||||||
|
info->cpu_cores = detected_threads;
|
||||||
|
strncpy(info->cpu, HW_ARCH, sizeof(info->cpu) - 1);
|
||||||
|
strncpy(info->operating_system, HW_OS, sizeof(info->operating_system) - 1);
|
||||||
|
#if defined(__clang__)
|
||||||
|
snprintf(info->compiler, sizeof(info->compiler), "Clang %s", __clang_version__);
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
snprintf(info->compiler, sizeof(info->compiler), "GCC %s", __VERSION__);
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
snprintf(info->compiler, sizeof(info->compiler), "MSVC %d", _MSC_VER);
|
||||||
|
#else
|
||||||
|
strncpy(info->compiler, "Unknown", sizeof(info->compiler) - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
{
|
||||||
|
struct utsname u;
|
||||||
|
if (uname(&u) == 0)
|
||||||
|
snprintf(info->kernel, sizeof(info->kernel), "%.62s %.64s", u.sysname, u.release);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static const char *const model_paths[] = {
|
||||||
|
"/sys/firmware/devicetree/base/compatible",
|
||||||
|
"/sys/firmware/devicetree/base/model",
|
||||||
|
"/proc/device-tree/compatible"
|
||||||
|
};
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < sizeof model_paths / sizeof model_paths[0]; i++)
|
||||||
|
if (read_first_property(model_paths[i], info->model,
|
||||||
|
sizeof info->model)) {
|
||||||
|
apple_m_name_from_soc(info->model, apple_soc, sizeof apple_soc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static const char *const soc_paths[] = {
|
||||||
|
"/sys/devices/soc0/family", "/sys/devices/soc0/machine",
|
||||||
|
"/sys/firmware/devicetree/base/compatible",
|
||||||
|
"/proc/device-tree/compatible"
|
||||||
|
};
|
||||||
|
char value[512]; unsigned i;
|
||||||
|
for (i = 0; !apple_soc[0] && i < sizeof soc_paths / sizeof soc_paths[0]; i++)
|
||||||
|
if (read_first_property(soc_paths[i], value, sizeof value))
|
||||||
|
apple_m_name_from_soc(value, apple_soc, sizeof apple_soc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
FILE *f = fopen("/proc/cpuinfo", "r");
|
||||||
|
char line[512];
|
||||||
|
int pairs[1024][2], npairs = 0, physical = -1, core = -1;
|
||||||
|
if (f) {
|
||||||
|
while (fgets(line, sizeof(line), f)) {
|
||||||
|
char *colon = strchr(line, ':');
|
||||||
|
if (!colon) continue;
|
||||||
|
*colon++ = '\0'; trim(line); trim(colon);
|
||||||
|
#if defined(__aarch64__) || defined(__arm__)
|
||||||
|
if (!strcmp(line, "CPU implementer")) {
|
||||||
|
arm_implementer = (unsigned)strtoul(colon, NULL, 0);
|
||||||
|
continue;
|
||||||
|
} else if (!strcmp(line, "CPU part")) {
|
||||||
|
unsigned part = (unsigned)strtoul(colon, NULL, 0);
|
||||||
|
int i, seen = 0;
|
||||||
|
for (i = 0; i < arm_core_count; i++)
|
||||||
|
if (arm_implementers[i] == arm_implementer && arm_parts[i] == part)
|
||||||
|
seen = 1;
|
||||||
|
if (!seen && arm_implementer && arm_core_count < 32) {
|
||||||
|
arm_implementers[arm_core_count] = arm_implementer;
|
||||||
|
arm_parts[arm_core_count++] = part;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((!strcmp(line, "model name") || !strcmp(line, "Processor") ||
|
||||||
|
!strcmp(line, "cpu")) && info->cpu[0] && !strcmp(info->cpu, HW_ARCH))
|
||||||
|
strncpy(info->cpu, colon, sizeof(info->cpu) - 1);
|
||||||
|
else if (!strcmp(line, "Hardware") && cpuinfo_hardware[0] == '\0')
|
||||||
|
strncpy(cpuinfo_hardware, colon, sizeof cpuinfo_hardware - 1);
|
||||||
|
else if (!strcmp(line, "physical id")) physical = atoi(colon);
|
||||||
|
else if (!strcmp(line, "core id")) core = atoi(colon);
|
||||||
|
if (physical >= 0 && core >= 0) {
|
||||||
|
int i, seen = 0;
|
||||||
|
for (i = 0; i < npairs; i++)
|
||||||
|
if (pairs[i][0] == physical && pairs[i][1] == core) seen = 1;
|
||||||
|
if (!seen && npairs < 1024) { pairs[npairs][0] = physical; pairs[npairs++][1] = core; }
|
||||||
|
physical = core = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
if (npairs > 0) info->cpu_cores = npairs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (apple_soc[0])
|
||||||
|
snprintf(info->cpu, sizeof info->cpu, "%s", apple_soc);
|
||||||
|
#if defined(__aarch64__) || defined(__arm__)
|
||||||
|
else {
|
||||||
|
/* Some kernels expose MIDR only through sysfs, not /proc/cpuinfo. */
|
||||||
|
if (arm_core_count == 0) {
|
||||||
|
long cpu;
|
||||||
|
for (cpu = 0; cpu < info->cpu_threads && cpu < 4096; cpu++) {
|
||||||
|
char path[128], value[64]; unsigned long midr;
|
||||||
|
int i, seen = 0;
|
||||||
|
snprintf(path, sizeof path,
|
||||||
|
"/sys/devices/system/cpu/cpu%ld/regs/identification/midr_el1", cpu);
|
||||||
|
if (!read_first_property(path, value, sizeof value)) continue;
|
||||||
|
midr = strtoul(value, NULL, 0);
|
||||||
|
for (i = 0; i < arm_core_count; i++)
|
||||||
|
if (arm_implementers[i] == ((midr >> 24) & 0xff) &&
|
||||||
|
arm_parts[i] == ((midr >> 4) & 0xfff)) seen = 1;
|
||||||
|
if (!seen && arm_core_count < 32) {
|
||||||
|
arm_implementers[arm_core_count] = (unsigned)((midr >> 24) & 0xff);
|
||||||
|
arm_parts[arm_core_count++] = (unsigned)((midr >> 4) & 0xfff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arm_core_count > 0) {
|
||||||
|
const char *apple_name = apple_m_name_from_midr(
|
||||||
|
arm_implementers, arm_parts, arm_core_count);
|
||||||
|
if (apple_name)
|
||||||
|
snprintf(info->cpu, sizeof info->cpu, "%s", apple_name);
|
||||||
|
else
|
||||||
|
format_arm_cores(info->cpu, sizeof info->cpu,
|
||||||
|
arm_implementers, arm_parts, arm_core_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Try the system files if CPU info is missing. */
|
||||||
|
#if defined(__aarch64__) || defined(__arm__)
|
||||||
|
if (info->model[0] == '\0')
|
||||||
|
read_first_property("/sys/class/dmi/id/product_name", info->model,
|
||||||
|
sizeof info->model);
|
||||||
|
#endif
|
||||||
|
if (info->model[0] == '\0' && cpuinfo_hardware[0] != '\0')
|
||||||
|
snprintf(info->model, sizeof info->model, "%s", cpuinfo_hardware);
|
||||||
|
{
|
||||||
|
FILE *f = fopen("/proc/meminfo", "r");
|
||||||
|
char line[256]; long kb;
|
||||||
|
if (f) {
|
||||||
|
while (fgets(line, sizeof(line), f)) {
|
||||||
|
if (sscanf(line, "MemTotal: %ld kB", &kb) == 1) {
|
||||||
|
info->memory_mb = kb / 1024;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
FILE *f = fopen("/etc/os-release", "r"); char line[512];
|
||||||
|
if (f) { while (fgets(line, sizeof(line), f)) if (!strncmp(line, "PRETTY_NAME=", 12)) {
|
||||||
|
char *v = line + 12; trim(v);
|
||||||
|
if (v[0] == '\"') { memmove(v, v + 1, strlen(v)); if (strlen(v) && v[strlen(v)-1] == '\"') v[strlen(v)-1] = '\0'; }
|
||||||
|
snprintf(info->operating_system, sizeof(info->operating_system), "%s", v); break;
|
||||||
|
} fclose(f); }
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
{
|
||||||
|
size_t n = sizeof(info->cpu); uint64_t mem = 0; size_t mn = sizeof(mem);
|
||||||
|
size_t model_n = sizeof(info->model);
|
||||||
|
int cores = 0; size_t cn = sizeof(cores);
|
||||||
|
char brand[sizeof info->cpu] = "";
|
||||||
|
if (sysctlbyname("machdep.cpu.brand_string", brand, &n, NULL, 0) == 0 && brand[0])
|
||||||
|
snprintf(info->cpu, sizeof info->cpu, "%s", brand);
|
||||||
|
else {
|
||||||
|
uint32_t family = 0; size_t fn = sizeof family;
|
||||||
|
const char *name = NULL;
|
||||||
|
if (sysctlbyname("hw.cpufamily", &family, &fn, NULL, 0) == 0) {
|
||||||
|
switch (family) {
|
||||||
|
case 0x1b588bb3u: name = "Apple M1"; break;
|
||||||
|
case 0xda33d83du: name = "Apple M2"; break;
|
||||||
|
case 0x8765edeau: name = "Apple M3"; break;
|
||||||
|
case 0x17d5b93au: name = "Apple M4"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
if (name == NULL) name = "Apple M-series";
|
||||||
|
#endif
|
||||||
|
if (name != NULL) snprintf(info->cpu, sizeof info->cpu, "%s", name);
|
||||||
|
}
|
||||||
|
sysctlbyname("hw.model", info->model, &model_n, NULL, 0);
|
||||||
|
if (sysctlbyname("hw.physicalcpu", &cores, &cn, NULL, 0) == 0) info->cpu_cores = cores;
|
||||||
|
if (sysctlbyname("hw.memsize", &mem, &mn, NULL, 0) == 0) info->memory_mb = (long)(mem / 1024 / 1024);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char product[64] = ""; size_t pn = sizeof(product);
|
||||||
|
struct utsname u;
|
||||||
|
if (sysctlbyname("kern.osproductversion", product, &pn, NULL, 0) == 0)
|
||||||
|
snprintf(info->operating_system, sizeof(info->operating_system), "macOS %s", product);
|
||||||
|
if (uname(&u) == 0)
|
||||||
|
snprintf(info->kernel, sizeof(info->kernel), "%.62s %.64s", u.sysname, u.release);
|
||||||
|
}
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
{
|
||||||
|
HKEY key;
|
||||||
|
char brand[sizeof info->cpu] = "";
|
||||||
|
DWORD type = 0, bytes = sizeof brand;
|
||||||
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
|
||||||
|
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
|
||||||
|
if (RegQueryValueExA(key, "ProcessorNameString", NULL, &type,
|
||||||
|
(BYTE *)brand, &bytes) == ERROR_SUCCESS &&
|
||||||
|
(type == REG_SZ || type == REG_EXPAND_SZ)) {
|
||||||
|
brand[sizeof brand - 1] = '\0'; trim(brand);
|
||||||
|
if (brand[0]) snprintf(info->cpu, sizeof info->cpu, "%s", brand);
|
||||||
|
}
|
||||||
|
RegCloseKey(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
MEMORYSTATUSEX ms;
|
||||||
|
ms.dwLength = sizeof(ms);
|
||||||
|
if (GlobalMemoryStatusEx(&ms))
|
||||||
|
info->memory_mb = (long)(ms.ullTotalPhys / 1024 / 1024);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXA version;
|
||||||
|
typedef LONG (WINAPI *rtl_get_version_fn)(OSVERSIONINFOEXA *);
|
||||||
|
rtl_get_version_fn rtl_get_version = (rtl_get_version_fn)(void *)
|
||||||
|
GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion");
|
||||||
|
memset(&version, 0, sizeof(version)); version.dwOSVersionInfoSize = sizeof(version);
|
||||||
|
if (rtl_get_version && rtl_get_version(&version) == 0) {
|
||||||
|
snprintf(info->operating_system, sizeof(info->operating_system),
|
||||||
|
"Windows %lu.%lu (build %lu)", (unsigned long)version.dwMajorVersion,
|
||||||
|
(unsigned long)version.dwMinorVersion, (unsigned long)version.dwBuildNumber);
|
||||||
|
snprintf(info->kernel, sizeof(info->kernel), "NT %lu.%lu build %lu",
|
||||||
|
(unsigned long)version.dwMajorVersion, (unsigned long)version.dwMinorVersion,
|
||||||
|
(unsigned long)version.dwBuildNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
{
|
||||||
|
/* Read the CPU name from CPUID. */
|
||||||
|
unsigned eax, ebx, ecx, edx, max_ext;
|
||||||
|
char brand[49];
|
||||||
|
int i;
|
||||||
|
__cpuid(0x80000000, eax, ebx, ecx, edx);
|
||||||
|
max_ext = eax;
|
||||||
|
if (max_ext >= 0x80000004) {
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
__cpuid(0x80000002u + (unsigned)i, eax, ebx, ecx, edx);
|
||||||
|
memcpy(brand + i * 16 + 0, &eax, 4);
|
||||||
|
memcpy(brand + i * 16 + 4, &ebx, 4);
|
||||||
|
memcpy(brand + i * 16 + 8, &ecx, 4);
|
||||||
|
memcpy(brand + i * 16 + 12, &edx, 4);
|
||||||
|
}
|
||||||
|
brand[48] = '\0';
|
||||||
|
trim(brand);
|
||||||
|
/* Prefer the registry name, which also works under ARM64 emulation. */
|
||||||
|
if (brand[0] && !strcmp(info->cpu, HW_ARCH))
|
||||||
|
snprintf(info->cpu, sizeof(info->cpu), "%s", brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef FOSSBENCH_HW_DETECT_H
|
||||||
|
#define FOSSBENCH_HW_DETECT_H
|
||||||
|
|
||||||
|
struct system_info {
|
||||||
|
char cpu[256];
|
||||||
|
char model[256];
|
||||||
|
char operating_system[256];
|
||||||
|
char compiler[128];
|
||||||
|
char kernel[128];
|
||||||
|
long cpu_cores;
|
||||||
|
long cpu_threads;
|
||||||
|
long memory_mb;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *hw_arch_name(void);
|
||||||
|
void hw_detect_system(struct system_info *info);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user