some system info improvements (CpuInfo, SystemInfo, SIMD helper)

This commit is contained in:
Dennis Eichhorn 2025-01-18 18:23:44 +01:00
parent 208bff208f
commit 2263d6f018
11 changed files with 726 additions and 871 deletions

20
architecture/CpuInfo.cpp Normal file
View File

@ -0,0 +1,20 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_ARCHITECTURE_CPU_INFO_C
#define TOS_ARCHITECTURE_CPU_INFO_C
#include "CpuInfo.h"
#if ARM
#include "arm/CpuInfo.cpp"
#else
#include "x86/CpuInfo.cpp"
#endif
#endif

101
architecture/CpuInfo.h Normal file
View File

@ -0,0 +1,101 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_ARCHITECTURE_CPU_INFO_H
#define TOS_ARCHITECTURE_CPU_INFO_H
#include "../stdlib/Types.h"
// @todo We don't care about a lot of features, consider to remove them if we can get either below 32bit
// or if we eventually overflow 64 bit
enum CPUFeature : uint64 {
CPU_FEATURE_SSE3 = 1ULL << 0,
CPU_FEATURE_PCLMULQDQ = 1ULL << 1,
CPU_FEATURE_MONITOR = 1ULL << 2,
CPU_FEATURE_SSSE3 = 1ULL << 3,
CPU_FEATURE_FMA = 1ULL << 4,
CPU_FEATURE_CMPXCHG16B = 1ULL << 5,
CPU_FEATURE_SSE41 = 1ULL << 6,
CPU_FEATURE_SSE42 = 1ULL << 7,
CPU_FEATURE_MOVBE = 1ULL << 8,
CPU_FEATURE_POPCNT = 1ULL << 9,
CPU_FEATURE_AES = 1ULL << 10,
CPU_FEATURE_XSAVE = 1ULL << 11,
CPU_FEATURE_OSXSAVE = 1ULL << 12,
CPU_FEATURE_AVX = 1ULL << 13,
CPU_FEATURE_F16C = 1ULL << 14,
CPU_FEATURE_RDRAND = 1ULL << 15,
CPU_FEATURE_MSR = 1ULL << 16,
CPU_FEATURE_CX8 = 1ULL << 17,
CPU_FEATURE_SEP = 1ULL << 18,
CPU_FEATURE_CMOV = 1ULL << 19,
CPU_FEATURE_CLFSH = 1ULL << 20,
CPU_FEATURE_MMX = 1ULL << 21,
CPU_FEATURE_FXSR = 1ULL << 22,
CPU_FEATURE_SSE = 1ULL << 23,
CPU_FEATURE_SSE2 = 1ULL << 24,
CPU_FEATURE_AVX2 = 1ULL << 25,
CPU_FEATURE_BMI1 = 1ULL << 26,
CPU_FEATURE_BMI2 = 1ULL << 27,
CPU_FEATURE_ERMS = 1ULL << 28,
CPU_FEATURE_INVPCID = 1ULL << 29,
CPU_FEATURE_RDSEED = 1ULL << 30,
CPU_FEATURE_ADX = 1ULL << 31,
CPU_FEATURE_SHA = 1ULL << 32,
CPU_FEATURE_PREFETCHWT1 = 1ULL << 33,
CPU_FEATURE_LAHF = 1ULL << 34,
CPU_FEATURE_LZCNT = 1ULL << 35,
CPU_FEATURE_ABM = 1ULL << 36,
CPU_FEATURE_SSE4a = 1ULL << 37,
CPU_FEATURE_XOP = 1ULL << 38,
CPU_FEATURE_TBM = 1ULL << 39,
CPU_FEATURE_SYSCALL = 1ULL << 40,
CPU_FEATURE_MMEXT = 1ULL << 41,
CPU_FEATURE_RDTSCP = 1ULL << 42,
CPU_FEATURE_3DNOWEXT = 1ULL << 43,
CPU_FEATURE_3DNOW = 1ULL << 44,
CPU_FEATURE_AVX512F = 1ULL << 45,
CPU_FEATURE_AVX512PF = 1ULL << 46,
CPU_FEATURE_AVX512ER = 1ULL << 47,
CPU_FEATURE_AVX512CD = 1ULL << 48,
CPU_FEATURE_ASIMD_ARM = 1ULL << 49,
CPU_FEATURE_ATOMICS_ARM = 1ULL << 50,
CPU_FEATURE_PMULL_ARM = 1ULL << 51,
CPU_FEATURE_SVEPMULL_ARM = 1ULL << 52,
CPU_FEATURE_NEON_ARM = 1ULL << 53,
CPU_FEATURE_SVE_ARM = 1ULL << 54,
CPU_FEATURE_SVE2_ARM = 1ULL << 55,
CPU_FEATURE_AES_ARM = 1ULL << 56,
CPU_FEATURE_SHA1_ARM = 1ULL << 57,
CPU_FEATURE_SHA2_ARM = 1ULL << 58,
CPU_FEATURE_CRC32_ARM = 1ULL << 59,
};
struct CpuCacheInfo {
uint32 size;
uint32 sets;
byte level;
byte ways;
byte partitions;
uint16 line_size;
};
struct CpuInfo {
char vendor[13];
char brand[49];
byte model;
byte family;
byte thread_count;
int32 mhz;
uint32 page_size;
CpuCacheInfo cache[4];
uint64 features;
};
#endif

View File

@ -0,0 +1,67 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_ARCHITECTURE_ARM_CPU_INFO_C
#define TOS_ARCHITECTURE_ARM_CPU_INFO_C
#include <stdio.h>
#include <stdint.h>
#include "../../stdlib/Types.h"
#include "../CpuInfo.h"
#include <arm_sve.h>
uint64 cpu_info_features() {
uint64 feature_bitfield = 0;
uint64 hwcap = getauxval(AT_HWCAP);
uint64 hwcap2 = getauxval(AT_HWCAP2);
if (hwcap & HWCAP_ASIMD) feature_bitfield |= CPU_FEATURE_ASIMD_ARM;
if (hwcap & HWCAP_ATOMICS) feature_bitfield |= CPU_FEATURE_ATOMICS_ARM;
if (hwcap & HWCAP_PMULL) feature_bitfield |= CPU_FEATURE_PMULL_ARM;
if (hwcap2 & HWCAP2_SVEPMULL) feature_bitfield |= CPU_FEATURE_SVEPMULL_ARM;
if (hwcap & HWCAP_NEON) feature_bitfield |= CPU_FEATURE_NEON_ARM;
if (hwcap & HWCAP_SVE) feature_bitfield |= CPU_FEATURE_SVE_ARM;
if (hwcap2 & HWCAP2_SVE) feature_bitfield |= CPU_FEATURE_SVE2_ARM;
if (hwcap & HWCAP_AES) feature_bitfield |= CPU_FEATURE_AES_ARM;
if (hwcap & HWCAP_SHA1) feature_bitfield |= CPU_FEATURE_SHA1_ARM;
if (hwcap & HWCAP_SHA2) feature_bitfield |= CPU_FEATURE_SHA2_ARM;
if (hwcap & HWCAP_CRC32) feature_bitfield |= CPU_FEATURE_CRC32_ARM;
return feature_bitfield;
}
void cpu_info_cache(int32_t level, CpuCacheInfo* cache) {
uint32_t ccsidr; // Cache Size ID Register
uint32_t line_size, associativity, num_sets;
cache->level = level;
cache->size = 0;
cache->ways = 0;
cache->partitions = 1; // Typically 1 on ARM
cache->sets = 0;
cache->line_size = 0;
// Select cache level and type in CSSELR
uint32_t csselr = level << 1; // Data or unified cache
__asm__ volatile("msr csselr_el1, %0" : : "r" (csselr));
__asm__ volatile("mrs %0, ccsidr_el1" : "=r" (ccsidr));
// Extract cache details from CCSIDR
line_size = (ccsidr & 0x7) + 4; // Line size in log2 words
associativity = ((ccsidr >> 3) & 0x3FF) + 1;
num_sets = ((ccsidr >> 13) & 0x7FFF) + 1;
// Populate the cache structure
cache->line_size = 1 << line_size; // Convert to bytes
cache->ways = associativity;
cache->sets = num_sets;
cache->size = cache->ways * cache->sets * cache->line_size;
}
#endif

View File

@ -0,0 +1,163 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_ARCHITECTURE_X86_CPU_INFO_C
#define TOS_ARCHITECTURE_X86_CPU_INFO_C
#include <stdio.h>
#include <stdint.h>
#include "../../stdlib/Types.h"
#include "../CpuInfo.h"
#ifdef _MSC_VER
#include <intrin.h>
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
__cpuidex(cpuInfo, function_id, 0);
}
#else
/*
#include <cpuid.h>
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
__cpuid(function_id, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
}
*/
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
__asm__ volatile(
"cpuid"
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
: "a" (function_id)
);
}
#endif
inline
int32 svcntw() {
return 0;
}
uint64 cpu_info_features() {
uint64 feature_bitfield = 0;
int32 cpuInfo[4] = {0};
// Query function 0x00000001
cpuid(cpuInfo, 0x00000001);
uint32 ecx = (uint32) cpuInfo[2];
uint32 edx = (uint32) cpuInfo[3];
// Map ECX features
if (ecx & (1 << 0)) feature_bitfield |= CPU_FEATURE_SSE3;
if (ecx & (1 << 1)) feature_bitfield |= CPU_FEATURE_PCLMULQDQ;
if (ecx & (1 << 3)) feature_bitfield |= CPU_FEATURE_MONITOR;
if (ecx & (1 << 9)) feature_bitfield |= CPU_FEATURE_SSSE3;
if (ecx & (1 << 12)) feature_bitfield |= CPU_FEATURE_FMA;
if (ecx & (1 << 13)) feature_bitfield |= CPU_FEATURE_CMPXCHG16B;
if (ecx & (1 << 19)) feature_bitfield |= CPU_FEATURE_SSE41;
if (ecx & (1 << 20)) feature_bitfield |= CPU_FEATURE_SSE42;
if (ecx & (1 << 22)) feature_bitfield |= CPU_FEATURE_MOVBE;
if (ecx & (1 << 23)) feature_bitfield |= CPU_FEATURE_POPCNT;
if (ecx & (1 << 25)) feature_bitfield |= CPU_FEATURE_AES;
if (ecx & (1 << 26)) feature_bitfield |= CPU_FEATURE_XSAVE;
if (ecx & (1 << 27)) feature_bitfield |= CPU_FEATURE_OSXSAVE;
if (ecx & (1 << 28)) feature_bitfield |= CPU_FEATURE_AVX;
if (ecx & (1 << 29)) feature_bitfield |= CPU_FEATURE_F16C;
if (ecx & (1 << 30)) feature_bitfield |= CPU_FEATURE_RDRAND;
// Map EDX features
if (edx & (1 << 5)) feature_bitfield |= CPU_FEATURE_MSR;
if (edx & (1 << 8)) feature_bitfield |= CPU_FEATURE_CX8;
if (edx & (1 << 11)) feature_bitfield |= CPU_FEATURE_SEP;
if (edx & (1 << 15)) feature_bitfield |= CPU_FEATURE_CMOV;
if (edx & (1 << 19)) feature_bitfield |= CPU_FEATURE_CLFSH;
if (edx & (1 << 23)) feature_bitfield |= CPU_FEATURE_MMX;
if (edx & (1 << 24)) feature_bitfield |= CPU_FEATURE_FXSR;
if (edx & (1 << 25)) feature_bitfield |= CPU_FEATURE_SSE;
if (edx & (1 << 26)) feature_bitfield |= CPU_FEATURE_SSE2;
// Query function 0x00000007
cpuid(cpuInfo, 0x00000007);
uint32 ebx = (uint32) cpuInfo[1];
uint32 ecx7 = (uint32) cpuInfo[2];
// Map EBX features
if (ebx & (1 << 3)) feature_bitfield |= CPU_FEATURE_BMI1;
if (ebx & (1 << 5)) feature_bitfield |= CPU_FEATURE_AVX2;
if (ebx & (1 << 8)) feature_bitfield |= CPU_FEATURE_BMI2;
if (ebx & (1 << 9)) feature_bitfield |= CPU_FEATURE_ERMS;
if (ebx & (1 << 10)) feature_bitfield |= CPU_FEATURE_INVPCID;
if (ebx & (1 << 16)) feature_bitfield |= CPU_FEATURE_AVX512F;
if (ebx & (1 << 18)) feature_bitfield |= CPU_FEATURE_RDSEED;
if (ebx & (1 << 19)) feature_bitfield |= CPU_FEATURE_ADX;
if (ebx & (1 << 26)) feature_bitfield |= CPU_FEATURE_AVX512PF;
if (ebx & (1 << 27)) feature_bitfield |= CPU_FEATURE_AVX512ER;
if (ebx & (1 << 28)) feature_bitfield |= CPU_FEATURE_AVX512CD;
if (ebx & (1 << 29)) feature_bitfield |= CPU_FEATURE_SHA;
// Map ECX features
if (ecx7 & (1 << 0)) feature_bitfield |= CPU_FEATURE_PREFETCHWT1;
// Query extended function 0x80000001
cpuid(cpuInfo, 0x80000001);
uint32 ecx81 = (uint32) cpuInfo[2];
uint32 edx81 = (uint32) cpuInfo[3];
// Map ECX extended features
if (ecx81 & (1 << 0)) feature_bitfield |= CPU_FEATURE_LAHF;
if (ecx81 & (1 << 5)) feature_bitfield |= CPU_FEATURE_LZCNT;
if (ecx81 & (1 << 6)) feature_bitfield |= CPU_FEATURE_ABM;
if (ecx81 & (1 << 11)) feature_bitfield |= CPU_FEATURE_XOP;
if (ecx81 & (1 << 21)) feature_bitfield |= CPU_FEATURE_TBM;
// Map EDX extended features
if (edx81 & (1 << 11)) feature_bitfield |= CPU_FEATURE_SYSCALL;
if (edx81 & (1 << 22)) feature_bitfield |= CPU_FEATURE_MMEXT;
if (edx81 & (1 << 27)) feature_bitfield |= CPU_FEATURE_RDTSCP;
if (edx81 & (1 << 30)) feature_bitfield |= CPU_FEATURE_3DNOWEXT;
if (edx81 & (1 << 31)) feature_bitfield |= CPU_FEATURE_3DNOW;
return feature_bitfield;
}
void cpu_info_cache(byte level, CpuCacheInfo* cache) {
uint32 eax, ebx, ecx, edx;
int32 type;
cache->level = level;
cache->size = 0;
cache->ways = 0;
cache->partitions = 0;
cache->sets = 0;
cache->line_size = 0;
int32 regs[4];
cpuid(regs, (0x04 << 8) | level);
eax = regs[0];
ebx = regs[1];
ecx = regs[2];
edx = regs[3];
type = (eax & 0x1F);
if (type == 0) {
return;
}
cache->ways = (byte) ((ebx >> 22) & 0x3FF) + 1;
cache->partitions = (byte) ((ebx >> 12) & 0x3FF) + 1;
cache->line_size = (uint16) (ebx & 0xFFF) + 1;
cache->sets = ecx + 1;
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
}
#endif

View File

@ -11,19 +11,49 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "../../stdlib/Types.h"
#include "../../system/SystemInfo.h"
#include "../../architecture/CpuInfo.cpp"
#include <locale.h>
#include <cpuid.h>
#include <sys/resource.h>
#if __aarch64__
#include "../../stdlib/SIMD_Helper.h"
#else
#include "../../stdlib/sve/SVE_Helper.h"
#endif
// @todo Implement own line by line file reading
// @todo implement for arm?
uint64 system_private_memory_usage()
{
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage) == 0) {
return usage.ru_maxrss * 1024; // Convert from kilobytes to bytes
} else {
return 0;
}
}
uint64 system_app_memory_usage()
{
FILE* fp = fopen("/proc/self/smaps", "r");
if (!fp) {
return 0;
}
uint64 total_size = 0;
char line[256];
while (fgets(line, sizeof(line), fp)) {
if (str_compare(line, "Private_Dirty:", sizeof("Private_Dirty:") - 1) == 0) {
uint64 private_dirty;
if (sscanf(line, "Private_Dirty: %lu kB", &private_dirty) == 1) {
total_size += private_dirty * 1024; // Convert from kB to bytes
}
}
}
fclose(fp);
return total_size;
}
uint16 system_language_code()
{
@ -39,263 +69,87 @@ uint16 system_country_code()
return (localeName[3] << 8) | localeName[4];
}
void cache_info_get(int32 level, CpuCacheInfo* cache) {
uint32 eax, ebx, ecx, edx;
int32 type;
cache->level = level;
cache->size = 0;
cache->ways = 0;
cache->partitions = 0;
cache->sets = 0;
cache->line_size = 0;
__cpuid_count(4, level, eax, ebx, ecx, edx);
type = (eax & 0x1F);
if (type == 0) {
return;
}
cache->ways = ((ebx >> 22) & 0x3FF) + 1;
cache->line_size = (ebx & 0xFFF) + 1;
cache->partitions = ((ebx >> 12) & 0x3FF) + 1;
cache->sets = ecx + 1;
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
}
void mainboard_info_get(MainboardInfo* info) {
info->name[63] = '\0';
info->serial_number[63] = '\0';
HRESULT hres;
FILE *fp;
// Step 1: Initialize COM library
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
return;
fp = fopen("/sys/class/dmi/id/board_name", "r");
if (fp) {
fgets(info->name, 64, fp);
fclose(fp);
}
// Step 2: Set general COM security levels
hres = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if (FAILED(hres)) {
CoUninitialize();
return;
fp = fopen("/sys/class/dmi/id/board_serial", "r");
if (fp) {
fgets(info->serial_number, 64, fp);
fclose(fp);
}
// Step 3: Obtain initial locator to WMI
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID *)&pLoc
);
if (FAILED(hres)) {
CoUninitialize();
return;
}
// Step 4: Connect to WMI through IWbemLocator::ConnectServer
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres)) {
pLoc->Release();
CoUninitialize();
return;
}
// Step 5: Set security levels on the proxy
hres = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
return;
}
// Step 6: Use the IWbemServices pointer to make a WMI query
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_BaseBoard"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
return;
}
// Step 7: Retrieve the data
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn) {
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"Product", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
snprintf(info->name, 64, "%S", vtProp.bstrVal);
VariantClear(&vtProp);
}
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
snprintf(info->serial_number, 63, "%S", vtProp.bstrVal);
info->serial_number[64] = '\0';
VariantClear(&vtProp);
}
pclsObj->Release();
}
// Clean up
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
info->name[strcspn(info->name, "\n")] = '\0';
info->serial_number[strcspn(info->serial_number, "\n")] = '\0';
}
int network_info_get(NetworkInfo* info) {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
return 0;
}
DWORD dwSize = 0;
PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL;
PIP_ADAPTER_ADDRESSES pAdapter = NULL;
// Get the size of the adapter addresses buffer
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) {
pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(dwSize);
if (pAdapterAddresses == NULL) {
WSACleanup();
return 0;
}
} else {
WSACleanup();
return 0;
}
// Get the adapter addresses
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAdapterAddresses, &dwSize) != NO_ERROR) {
free(pAdapterAddresses);
WSACleanup();
return 0;
}
int32 network_info_get(NetworkInfo* info) {
char path[256];
struct stat st;
int32 i = 0;
// Iterate over the adapters and print their MAC addresses
pAdapter = pAdapterAddresses;
while (pAdapter && i < 4) {
if (pAdapter->PhysicalAddressLength != 0) {
info[i].slot[63] = '\0';
for (i = 0; i < 4; i++) {
sprintf_fast(path, "/sys/class/net/eth%d", i);
if (stat(path, &st) == 0) {
// Read MAC address
sprintf_fast(path, "/sys/class/net/eth%d/address", i);
FILE *mac_file = fopen(path, "r");
if (mac_file) {
fscanf(mac_file, "%s", info[i].mac);
fclose(mac_file);
}
// Read interface name
sprintf_fast(path, "/sys/class/net/eth%d/ifindex", i);
FILE *index_file = fopen(path, "r");
if (index_file) {
fscanf(index_file, "%s", info[i].slot);
fclose(index_file);
}
info[i].mac[23] = '\0';
memcpy(info[i].mac, pAdapter->PhysicalAddress, 8);
wcstombs(info[i].slot, pAdapter->FriendlyName, 63);
++i;
info[i].slot[63] = '\0';
}
pAdapter = pAdapter->Next;
}
free(pAdapterAddresses);
WSACleanup();
return i;
}
void cpu_info_get(CpuInfo* info) {
int32 temp;
info->simd.sse = (temp = max_sse_supported()) > 9 ? temp / 10.0f : temp;
info->simd.avx256 = max_avx256_supported();
info->simd.avx512 = max_avx512_supported();
cache_info_get(1, &info->cache[0]);
cache_info_get(2, &info->cache[1]);
cache_info_get(3, &info->cache[2]);
cache_info_get(4, &info->cache[3]);
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
info->page_size = sys_info.dwPageSize;
int32 cpuInfo[4] = { 0 };
__cpuid(cpuInfo, 0);
memset(info->vendor, 0, sizeof(info->vendor));
*((int*)info->vendor) = cpuInfo[1];
*((int*)(info->vendor + 4)) = cpuInfo[3];
*((int*)(info->vendor + 8)) = cpuInfo[2];
info->vendor[12] = '\0';
__cpuid(cpuInfo, 0x80000002);
memcpy(info->brand, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000003);
memcpy(info->brand + 16, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000004);
memcpy(info->brand + 32, cpuInfo, sizeof(cpuInfo));
info->brand[48] = '\0';
__cpuid(cpuInfo, 1);
info->model = (cpuInfo[0] >> 4) & 0xF;
info->family = (cpuInfo[0] >> 8) & 0xF;
DWORD bufSize = sizeof(DWORD);
HKEY hKey;
long lError = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
0, KEY_READ, &hKey
);
if (lError == ERROR_SUCCESS) {
RegQueryValueExA(hKey, "~MHz", NULL, NULL, (LPBYTE) &(info->mhz), &bufSize);
FILE* fp = fopen("/proc/cpuinfo", "r");
if (!fp) {
return;
}
RegCloseKey(hKey);
char line[256];
while (fgets(line, sizeof(line), fp)) {
if (str_compare(line, "vendor_id", 9) == 0) {
sscanf(line, "vendor_id : %s", info->vendor);
} else if (str_compare(line, "model", 5) == 0) {
sscanf(line, "model : %d", &info->model);
} else if (str_compare(line, "cpu MHz", 7) == 0) {
sscanf(line, "cpu MHz : %d", &info->mhz);
} else if (str_compare(line, "cpu cores", 10) == 0) {
sscanf(line, "cpu cores : %d", &info->thread_coun);
} else if (str_compare(line, "model name", 10) == 0) {
sscanf(line, "model name : %63[^\n]", info->brand);
}
}
fclose(fp);
info->family = 0;
info->page_size = 4096; // Assuming standard page size of 4KB in Linux
}
void os_info_get(OSInfo* info) {
@ -303,167 +157,111 @@ void os_info_get(OSInfo* info) {
memcpy(info->name, "Linux", sizeof("Linux"));
info->major = 0;
info->minor = 0;
info->vendor[sizeof("Linux")] = '\0';
info->name[sizeof("Linux")] = '\0';
}
void ram_info_get(RamInfo* info) {
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
info->memory = (int) (statex.ullTotalPhys / (1024 * 1024));
FILE* fp = fopen("/proc/meminfo", "r");
if (fp == NULL) {
return;
}
char line[256];
uint32 total_memory = 0;
while (fgets(line, sizeof(line), fp)) {
if (sscanf(line, "MemTotal: %u kB", &total_memory) == 1) {
break;
}
}
fclose(fp);
// Convert memory from kB to MB
info->memory = total_memory / 1024;
}
uint32 gpu_info_get(GpuInfo* info) {
IDXGIFactory *pFactory = NULL;
IDXGIAdapter *pAdapter = NULL;
DXGI_ADAPTER_DESC adapterDesc;
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory);
if (FAILED(hr)) {
FILE* fp = popen("lspci | grep VGA", "r");
if (fp == NULL) {
return 0;
}
uint32 i = 0;
while (pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND && i < 2) {
hr = pAdapter->GetDesc(&adapterDesc);
if (FAILED(hr)) {
pAdapter->Release();
break;
uint32 count = 0;
char line[256];
while (fgets(line, sizeof(line), fp)) {
if (count >= 2) break;
// Assuming that the first part of the line contains the name of the GPU
char* gpu_name = strtok(line, ":");
if (gpu_name) {
sprintf_fast(info[count].name, sizeof(info[count].name), "%s", gpu_name);
}
wcstombs(info[i].name, adapterDesc.Description, 63);
info[i].name[63] = '\0';
info[i].vram = (int) (adapterDesc.DedicatedVideoMemory / (1024 * 1024));
// @todo this is Wrong
info[count].vram = 2048;
pAdapter->Release();
i++;
count++;
}
pFactory->Release();
fclose(fp);
return i;
return count;
}
void display_info_get_primary(DisplayInfo* info) {
FILE* fp = popen("xrandr --current", "r");
if (fp == NULL) {
return;
}
char line[256];
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, "primary")) {
// Example of a line containing display info: "HDMI-1 connected 1920x1080+0+0 60.00*+"
char name[64];
uint32 width, height, hz;
if (sscanf(line, "%s connected %dx%d+%*d+%*d %d", name, &width, &height, &hz) == 4) {
str_copy_short(info->name, name);
info->width = width;
info->height = height;
info->hz = hz;
}
break;
}
}
fclose(fp);
}
uint32 display_info_get(DisplayInfo* info) {
DISPLAY_DEVICEA device;
DEVMODEA mode;
device.cb = sizeof(DISPLAY_DEVICEA);
uint32 i = 0;
while (EnumDisplayDevicesA(NULL, i, &device, 0)) {
mode.dmSize = sizeof(mode);
if (EnumDisplaySettingsA(device.DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
str_copy_short(info[i].name, device.DeviceName);
info[i].width = mode.dmPelsWidth;
info[i].height = mode.dmPelsHeight;
info[i].hz = mode.dmDisplayFrequency;
}
++i;
FILE* fp = popen("xrandr --current", "r");
if (fp == NULL) {
return 0;
}
return i;
}
char line[256];
uint32 count = 0;
void system_info_render(char* buf, const SystemInfo* info) {
const char avx512[8][12] = {
"AVX-512F",
"AVX-512DQ",
"AVX-512IFMA",
"AVX-512PF",
"AVX-512ER",
"AVX-512CD",
"AVX-512BW",
"AVX-512VL"
};
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, "connected")) {
// Example: "HDMI-1 connected 1920x1080+0+0 60.00*+"
char name[64];
uint32 width, height, hz;
if (sscanf(line, "%s connected %dx%d+%*d+%*d %d", name, &width, &height, &hz) == 4) {
str_copy_short(info[count].name, name);
info[count].width = width;
info[count].height = height;
info[count].hz = hz;
count++;
}
}
}
sprintf_s(
buf,
"OS:\n"
"==============\n"
"Vendor: %s\n" "Name: %s\n" "Major: %d\n" "Minor: %d\n"
"\n"
"Mainboard:\n"
"==============\n"
"Name: %s\n" "SN: %s\n"
"\n"
"Network:\n"
"==============\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"CPU:\n"
"==============\n"
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Page Size: %d\n"
"\n"
"Cache:\n"
"L1: Size %d Line %d\n"
"L2: Size %d Line %d\n"
"L3: Size %d Line %d\n"
"L4: Size %d Line %d\n"
"\n"
"SIMD:\n" "SSE: %.1f\n" "AVX256: %d\n" "AVX512: %s\n"
"\n"
"GPU:\n"
"==============\n"
"Name: %s\n" "VRAM: %d\n"
"Name: %s\n" "VRAM: %d\n"
"\n"
"Display:\n"
"==============\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"\n"
"RAM:\n"
"==============\n"
"Memory: %d MB",
info->os.vendor, info->os.name, info->os.major, info->os.minor,
info->mainboard.name, info->mainboard.serial_number,
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
info->network_count < 2 ? "" : info->network[1].slot, info->network_count < 2 ? 0 : info->network[1].mac[0], info->network_count < 2 ? 0 : info->network[1].mac[1], info->network_count < 2 ? 0 : info->network[1].mac[2], info->network_count < 2 ? 0 : info->network[1].mac[3], info->network_count < 2 ? 0 : info->network[1].mac[4], info->network_count < 2 ? 0 : info->network[1].mac[5], info->network_count < 2 ? 0 : info->network[1].mac[6], info->network_count < 2 ? 0 : info->network[1].mac[7],
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.page_size,
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0",
info->gpu[0].name, info->gpu[0].vram,
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz,
info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz,
info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz,
info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz,
info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz,
info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz,
info->ram.memory
);
}
fclose(fp);
void system_info_get(SystemInfo* info)
{
os_info_get(&info->os);
mainboard_info_get(&info->mainboard);
info->network_count = network_info_get(info->network);
cpu_info_get(&info->cpu);
ram_info_get(&info->ram);
info->gpu_count = gpu_info_get(info->gpu);
info->display_count = display_info_get(info->display);
return count;
}
#endif

View File

@ -6,8 +6,8 @@
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_UTILS_FAST_PIPES_H
#define TOS_UTILS_FAST_PIPES_H
#ifndef TOS_PLATFORM_WIN32_FAST_PIPES_H
#define TOS_PLATFORM_WIN32_FAST_PIPES_H
#include "../stdlib/Types.h"

View File

@ -12,7 +12,9 @@
#include <stdio.h>
#include <stdint.h>
#include "../../stdlib/Types.h"
#include "../../utils/StringUtils.h"
#include "../../system/SystemInfo.h"
#include "../../architecture/CpuInfo.cpp"
#include <psapi.h>
#include <winsock2.h>
@ -27,12 +29,6 @@
#include <wingdi.h>
#include <hidsdi.h>
#if __aarch64__
#include "../../stdlib/sve/SVE_Helper.h"
#else
#include "../../stdlib/SIMD_Helper.h"
#endif
// @performance Do we really need all these libs, can't we simplify that?!
#include <intrin.h>
#pragma comment(lib, "Advapi32.lib")
@ -42,8 +38,6 @@
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "Ws2_32.lib")
// @todo implement for arm?
uint64 system_private_memory_usage()
{
PROCESS_MEMORY_COUNTERS_EX pmc;
@ -99,37 +93,6 @@ uint16 system_country_code()
return (local_name[3] << 8) | local_name[4];
}
void cache_info_get(int32 level, CpuCacheInfo* cache) {
uint32 eax, ebx, ecx, edx;
int32 type;
cache->level = level;
cache->size = 0;
cache->ways = 0;
cache->partitions = 0;
cache->sets = 0;
cache->line_size = 0;
int32 regs[4];
__cpuidex(regs, 4, level);
eax = regs[0];
ebx = regs[1];
ecx = regs[2];
edx = regs[3];
type = (eax & 0x1F);
if (type == 0) {
return;
}
cache->ways = ((ebx >> 22) & 0x3FF) + 1;
cache->line_size = (ebx & 0xFFF) + 1;
cache->partitions = ((ebx >> 12) & 0x3FF) + 1;
cache->sets = ecx + 1;
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
}
void mainboard_info_get(MainboardInfo* info) {
info->name[63] = '\0';
info->serial_number[63] = '\0';
@ -242,13 +205,15 @@ void mainboard_info_get(MainboardInfo* info) {
VARIANT vtProp;
hr = pclsObj->Get(L"Product", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
snprintf(info->name, 64, "%S", vtProp.bstrVal);
wchar_to_char(vtProp.bstrVal);
sprintf_fast(info->name, sizeof(info->name), "%s", vtProp.bstrVal);
VariantClear(&vtProp);
}
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
snprintf(info->serial_number, 63, "%S", vtProp.bstrVal);
wchar_to_char(vtProp.bstrVal);
sprintf_fast(info->serial_number, sizeof(info->serial_number), "%s", vtProp.bstrVal);
info->serial_number[64] = '\0';
VariantClear(&vtProp);
@ -264,7 +229,7 @@ void mainboard_info_get(MainboardInfo* info) {
CoUninitialize();
}
int network_info_get(NetworkInfo* info) {
int32 network_info_get(NetworkInfo* info) {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
return 0;
@ -319,22 +284,17 @@ int network_info_get(NetworkInfo* info) {
}
void cpu_info_get(CpuInfo* info) {
info->simd.sse = max_sse_supported();
info->simd.avx256 = max_avx256_supported();
info->simd.avx512 = max_avx512_supported();
info->simd.sve = max_sve_supported();
info->simd.neon = max_neon_supported();
info->simd.abm = supports_abm();
info->features = cpu_info_features();
cache_info_get(1, &info->cache[0]);
cache_info_get(2, &info->cache[1]);
cache_info_get(3, &info->cache[2]);
cache_info_get(4, &info->cache[3]);
cpu_info_cache(1, &info->cache[0]);
cpu_info_cache(2, &info->cache[1]);
cpu_info_cache(3, &info->cache[2]);
cpu_info_cache(4, &info->cache[3]);
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
info->thread_count = sys_info.dwNumberOfProcessors;
info->page_size = sys_info.dwPageSize;
info->thread_count = (byte) sys_info.dwNumberOfProcessors;
info->page_size = (uint16) sys_info.dwPageSize;
int32 cpuInfo[4] = { 0 };
__cpuid(cpuInfo, 0);
@ -376,32 +336,25 @@ void os_info_get(OSInfo* info) {
info->vendor[15] = '\0';
info->name[63] = '\0';
#if defined(_WIN32) || defined(_WIN64)
OSVERSIONINFOEXW version_info;
memset(&version_info, 0, sizeof(OSVERSIONINFOEXW));
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
NTSTATUS(WINAPI *RtlGetVersion)(OSVERSIONINFOEXW*) = (NTSTATUS(WINAPI *)(OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion");
if (RtlGetVersion != nullptr) {
RtlGetVersion(&version_info);
}
OSVERSIONINFOEXW version_info;
memset(&version_info, 0, sizeof(OSVERSIONINFOEXW));
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
NTSTATUS(WINAPI *RtlGetVersion)(OSVERSIONINFOEXW*) = (NTSTATUS(WINAPI *)(OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion");
if (RtlGetVersion != nullptr) {
RtlGetVersion(&version_info);
}
memcpy(info->vendor, "Microsoft", sizeof("Microsoft"));
memcpy(info->name, "Windows", sizeof("Windows"));
info->major = version_info.dwMajorVersion;
info->minor = version_info.dwMinorVersion;
#else
memcpy(info->vendor, "Linux", sizeof("Linux"));
memcpy(info->name, "Linux", sizeof("Linux"));
info->major = 0;
info->minor = 0;
#endif
memcpy(info->vendor, "Microsoft", sizeof("Microsoft"));
memcpy(info->name, "Windows", sizeof("Windows"));
info->major = version_info.dwMajorVersion;
info->minor = version_info.dwMinorVersion;
}
void ram_info_get(RamInfo* info) {
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
info->memory = (int) (statex.ullTotalPhys / (1024 * 1024));
info->memory = (uint32) (statex.ullTotalPhys / (1024 * 1024));
}
uint32 gpu_info_get(GpuInfo* info) {
@ -424,7 +377,7 @@ uint32 gpu_info_get(GpuInfo* info) {
wcstombs(info[i].name, adapterDesc.Description, 63);
info[i].name[63] = '\0';
info[i].vram = (int) (adapterDesc.DedicatedVideoMemory / (1024 * 1024));
info[i].vram = (uint32) (adapterDesc.DedicatedVideoMemory / (1024 * 1024));
pAdapter->Release();
i++;
@ -486,103 +439,4 @@ uint32 display_info_get(DisplayInfo* info) {
return i;
}
void system_info_render(char* buf, const SystemInfo* info) {
const char avx512[8][12] = {
"AVX-512F",
"AVX-512DQ",
"AVX-512IFMA",
"AVX-512PF",
"AVX-512ER",
"AVX-512CD",
"AVX-512BW",
"AVX-512VL"
};
sprintf_s(
buf,
4096,
"OS:\n"
"==============\n"
"Vendor: %s\n" "Name: %s\n" "Major: %d\n" "Minor: %d\n"
"\n"
"Mainboard:\n"
"==============\n"
"Name: %s\n" "SN: %s\n"
"\n"
"Network:\n"
"==============\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"CPU:\n"
"==============\n"
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Thread Count: %d\n" "Page Size: %d\n"
"\n"
"Cache:\n"
"L1: Size %d Line %d\n"
"L2: Size %d Line %d\n"
"L3: Size %d Line %d\n"
"L4: Size %d Line %d\n"
"\n"
"SIMD:\n" "SSE: %.1f\n" "AVX256: %d\n" "AVX512: %s\n" "SVE: %d\n" "NEON: %d\n" "ABM: %d\n"
"\n"
"GPU:\n"
"==============\n"
"Name: %s\n" "VRAM: %d\n"
"Name: %s\n" "VRAM: %d\n"
"\n"
"Display:\n"
"==============\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"\n"
"RAM:\n"
"==============\n"
"Memory: %d MB",
info->os.vendor, info->os.name, info->os.major, info->os.minor,
info->mainboard.name, info->mainboard.serial_number,
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
info->network_count < 2 ? "" : info->network[1].slot, info->network_count < 2 ? 0 : info->network[1].mac[0], info->network_count < 2 ? 0 : info->network[1].mac[1], info->network_count < 2 ? 0 : info->network[1].mac[2], info->network_count < 2 ? 0 : info->network[1].mac[3], info->network_count < 2 ? 0 : info->network[1].mac[4], info->network_count < 2 ? 0 : info->network[1].mac[5], info->network_count < 2 ? 0 : info->network[1].mac[6], info->network_count < 2 ? 0 : info->network[1].mac[7],
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.thread_count, info->cpu.page_size,
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
info->cpu.simd.sse > 9 ? (f32) info->cpu.simd.sse / 10.0f : (f32) info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0", info->cpu.simd.sve, info->cpu.simd.neon, (int32) info->cpu.simd.abm,
info->gpu[0].name, info->gpu[0].vram,
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz,
info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz,
info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz,
info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz,
info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz,
info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz,
info->ram.memory
);
}
void system_info_get(SystemInfo* info)
{
os_info_get(&info->os);
mainboard_info_get(&info->mainboard);
info->network_count = network_info_get(info->network);
cpu_info_get(&info->cpu);
ram_info_get(&info->ram);
info->gpu_count = gpu_info_get(info->gpu);
info->display_count = display_info_get(info->display);
display_info_get_primary(&info->display_primary);
info->language = system_language_code();
}
#endif

View File

@ -1,284 +0,0 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_STDLIB_SIMD_HELPER_H
#define TOS_STDLIB_SIMD_HELPER_H
#include <stdint.h>
#include <immintrin.h>
#include <xmmintrin.h>
#include "Types.h"
// @todo split into platform code for windows and linux
#if _WIN32
#include <windows.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#elif __linux__
#include <sys/auxv.h>
#include <unistd.h>
#endif
#if ARM
#include <arm_sve.h>
#else
int32 svcntw() {
return 0;
}
#endif
enum SIMDVersion {
SIMD_VERSION_NONE,
SIMD_VERSION_128,
SIMD_VERSION_256,
SIMD_VERSION_512,
SIMD_VERSION_SVE,
SIMD_VERSION_NEON,
};
// @todo implement for arm?
inline int32 max_neon_supported()
{
#if ARM
#if _WIN32
int cpu_info[4] = {0};
__cpuid(cpu_info, 0);
if (cpu_info[3] & (1 << 1)) {
return 1;
}
#else
unsigned int eax, ebx, ecx, edx;
__asm__ volatile (
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(0)
);
if (edx & (1 << 1)) {
return 1;
}
#endif
return 0;
#else
return 0;
#endif
}
inline int32 max_sve_supported()
{
#if ARM
int32 hwcaps = getauxval(AT_HWCAP);
return (int32) ((bool) (hwcaps & (1 << 19)));
#else
return 0;
#endif
}
inline int32 max_sse_supported()
{
#if ARM
return 0;
#else
#ifdef _MSC_VER
int32 cpuInfo[4] = {-1};
__cpuid(cpuInfo, 1); // CPUID function 1
uint32 ecx = cpuInfo[2];
uint32 edx = cpuInfo[3];
#else
uint32 eax, ebx, ecx, edx;
eax = 1; // CPUID function 1
__asm__ __volatile__("cpuid;"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(eax));
#endif
bool sse42_supported = (ecx >> 20) & 1;
if (sse42_supported) {
return 42;
}
bool sse41_supported = (ecx >> 19) & 1;
if (sse41_supported) {
return 41;
}
bool sse3_supported = (ecx >> 0) & 1;
if (sse3_supported) {
return 3;
}
bool sse2_supported = (edx >> 26) & 1;
if (sse2_supported) {
return 2;
}
return 0;
#endif
}
inline
int32 max_avx256_supported()
{
#if ARM
return 0;
#else
int32 max_version = 0;
#ifdef _MSC_VER
int32 cpuInfo[4];
__cpuid(cpuInfo, 1);
if ((cpuInfo[2] >> 28) & 1) {
__cpuid(cpuInfo, 7); // Query extended features
if ((cpuInfo[1] >> 5) & 1) {
max_version = 2;
}
}
#else
uint32 eax, ebx, ecx, edx;
__asm__ __volatile__("cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(1));
if ((ecx >> 28) & 1) {
eax = 7;
ecx = 0;
__asm__ __volatile__("cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(eax), "c"(ecx));
if ((ebx >> 5) & 1) {
max_version = 2;
}
}
#endif
return max_version;
#endif
}
inline
int32 max_avx512_supported()
{
#if ARM
return 0;
#else
#ifdef _MSC_VER
int32 cpuInfo[4];
__cpuid(cpuInfo, 1);
int32 ebx = 0;
if ((cpuInfo[2] >> 28) & 1) {
__cpuid(cpuInfo, 7);
ebx = cpuInfo[1];
}
#else
uint32 eax, ebx, ecx, edx;
__asm__ __volatile__("cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(1));
if ((ecx >> 28) & 1) {
eax = 7;
ecx = 0;
__asm__ __volatile__("cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(eax), "c"(ecx));
}
#endif
if ((ebx >> 16) & 1) {
return 1; // AVX-512F
}
if ((ebx >> 17) & 1) {
return 2; // AVX-512DQ
}
if ((ebx >> 21) & 1) {
return 3; // AVX-512IFMA
}
if ((ebx >> 26) & 1) {
return 4; // AVX-512PF
}
if ((ebx >> 27) & 1) {
return 5; // AVX-512ER
}
if ((ebx >> 28) & 1) {
return 6; // AVX-512CD
}
if ((ebx >> 30) & 1) {
return 7; // AVX-512BW
}
if ((ebx >> 31) & 1) {
return 8; // AVX-512VL
}
return 0;
#endif
}
const char AVX512_VERSIONS[8][12] = {
"AVX-512F",
"AVX-512DQ",
"AVX-512IFMA",
"AVX-512PF",
"AVX-512ER",
"AVX-512CD",
"AVX-512BW",
"AVX-512VL"
};
bool supports_abm() {
#if ARM
return 0;
#else
bool popcnt_supported;
bool lzcnt_supported;
#ifdef _MSC_VER
int cpuInfo[4];
__cpuid(cpuInfo, 0x80000001);
popcnt_supported = (cpuInfo[2] & (1 << 5)) != 0;
lzcnt_supported = (cpuInfo[1] & (1 << 5)) != 0;
#else
uint32 eax, ebx, ecx, edx;
eax = 0x80000001;
__asm__ __volatile__ (
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(eax)
);
// Check if the ABM (POPCNT and LZCNT) bits are set
popcnt_supported = (ecx & (1 << 5)) != 0;
lzcnt_supported = (ebx & (1 << 5)) != 0;
#endif
return popcnt_supported && lzcnt_supported;
#endif
}
#endif

View File

@ -15,4 +15,92 @@
#include "../platform/linux/SystemInfo.cpp"
#endif
void system_info_render(char* buf, const SystemInfo* info) {
sprintf_s(
buf,
4096,
"OS:\n"
"==============\n"
"Vendor: %s\n" "Name: %s\n" "Major: %d\n" "Minor: %d\n"
"\n"
"Mainboard:\n"
"==============\n"
"Name: %s\n" "SN: %s\n"
"\n"
"Network:\n"
"==============\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
"\n"
"CPU:\n"
"==============\n"
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Thread Count: %d\n" "Page Size: %d\n"
"\n"
"Cache:\n"
"L1: Size %d Line %d\n"
"L2: Size %d Line %d\n"
"L3: Size %d Line %d\n"
"L4: Size %d Line %d\n"
"\n"
"Features: %lld\n"
"\n"
"GPU:\n"
"==============\n"
"Name: %s\n" "VRAM: %d\n"
"Name: %s\n" "VRAM: %d\n"
"\n"
"Display:\n"
"==============\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
"\n"
"RAM:\n"
"==============\n"
"Memory: %d MB",
info->os.vendor, info->os.name, info->os.major, info->os.minor,
info->mainboard.name, info->mainboard.serial_number,
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
info->network_count < 2 ? "" : info->network[1].slot, info->network_count < 2 ? 0 : info->network[1].mac[0], info->network_count < 2 ? 0 : info->network[1].mac[1], info->network_count < 2 ? 0 : info->network[1].mac[2], info->network_count < 2 ? 0 : info->network[1].mac[3], info->network_count < 2 ? 0 : info->network[1].mac[4], info->network_count < 2 ? 0 : info->network[1].mac[5], info->network_count < 2 ? 0 : info->network[1].mac[6], info->network_count < 2 ? 0 : info->network[1].mac[7],
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.thread_count, info->cpu.page_size,
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
info->cpu.features,
info->gpu[0].name, info->gpu[0].vram,
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz,
info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz,
info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz,
info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz,
info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz,
info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz,
info->ram.memory
);
}
void system_info_get(SystemInfo* info)
{
os_info_get(&info->os);
mainboard_info_get(&info->mainboard);
info->network_count = network_info_get(info->network);
cpu_info_get(&info->cpu);
ram_info_get(&info->ram);
info->gpu_count = gpu_info_get(info->gpu);
info->display_count = display_info_get(info->display);
display_info_get_primary(&info->display_primary);
info->language = system_language_code();
}
#endif

View File

@ -10,15 +10,7 @@
#define TOS_SYSTEM_INFO_H
#include "../stdlib/Types.h"
struct CpuCacheInfo {
int32 level;
int32 size;
int32 ways;
int32 partitions;
int32 sets;
int32 line_size;
};
#include "../architecture/CpuInfo.h"
// @todo add vendor name
struct MainboardInfo {
@ -29,28 +21,7 @@ struct MainboardInfo {
// @todo add ipv6
struct NetworkInfo {
char slot[64];
byte mac[8];
};
struct SIMDInfo {
int32 sse;
int32 avx256;
int32 avx512;
int32 sve;
int32 neon;
bool abm;
};
struct CpuInfo {
char vendor[13];
char brand[49];
int32 model;
int32 family;
int32 thread_count;
int32 mhz;
CpuCacheInfo cache[4];
int32 page_size;
SIMDInfo simd;
byte mac[24];
};
struct OSInfo {
@ -61,12 +32,12 @@ struct OSInfo {
};
struct RamInfo {
int32 memory;
uint32 memory;
};
struct GpuInfo {
char name[64];
int32 vram;
uint32 vram;
};
struct DisplayInfo {

View File

@ -1277,6 +1277,83 @@ void sprintf_fast(char* __restrict buffer, const char* __restrict format, ...) {
va_end(args);
}
void sprintf_fast(char* __restrict buffer, int32 buffer_length, const char* __restrict format, ...) {
va_list args;
va_start(args, format);
// We start at 1 since we need 1 char for '\0'
int32 length = 1;
int32 offset;
while (*format && length < buffer_length) {
offset = 1;
if (*format != '%') {
*buffer++ = *format;
} else if (*format == '\\' && *(format + 1) == '%') {
++format;
*buffer++ = *format;
} else {
++format;
switch (*format) {
case 's': {
const char* str = va_arg(args, const char*);
--offset;
while (*str) {
*buffer++ = *str++;
++offset;
}
} break;
case 'c': {
*buffer++ = va_arg(args, char);
} break;
case 'n': {
int64 val = va_arg(args, int64);
buffer += offset = int_to_str(val, buffer, ',');
} break;
case 'd': {
int32 val = va_arg(args, int32);
buffer += offset = int_to_str(val, buffer);
} break;
case 'l': {
int64 val = va_arg(args, int64);
buffer += offset = int_to_str(val, buffer);
} break;
case 'f': {
f64 val = va_arg(args, f64);
// Default precision
int32 precision = 5;
// Check for optional precision specifier
const char* prec_ptr = format + 1;
if (*prec_ptr >= '0' && *prec_ptr <= '9') {
precision = 0;
while (*prec_ptr >= '0' && *prec_ptr <= '9') {
precision = precision * 10 + (*prec_ptr - '0');
prec_ptr++;
}
format = prec_ptr - 1;
}
buffer += offset = float_to_str(val, buffer, precision);
} break;
default: {
// Handle unknown format specifiers
*buffer++ = '%';
} break;
}
}
length += offset;
++format;
}
*buffer = '\0';
va_end(args);
}
// There are situations where you only want to replace a certain amount of %
void sprintf_fast_iter(char* buffer, const char* format, ...) {
va_list args;