Release 0.2.1 with expanded hardware detection

This commit is contained in:
2026-07-19 16:54:18 -05:00
parent e8f701a43b
commit 9a13869052
4 changed files with 565 additions and 255 deletions
+14 -13
View File
@@ -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
View File
@@ -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) {
+528
View File
@@ -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
}
+18
View File
@@ -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