diff --git a/corinfo.h b/corinfo.h new file mode 100644 index 0000000..1702044 --- /dev/null +++ b/corinfo.h @@ -0,0 +1,202 @@ +/* +* Part of corinfo, a library for obtaining CPU, RAM and GPU information. +* https://github.com/ColumbusUtrigas/corinfo +* +* Copyright (c) 2018 ColumbusUtrigas. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +#ifndef CORINFO_H +#define CORINFO_H + +#if !defined(__linux) && !defined(_WIN32) + #error "Unsupported platform" +#endif + +#ifdef __linux + #include + #include +#endif + +#include +#include +#include +#include + +/*! +* @file corinfo.h +*/ + +struct corinfo +{ + uint32_t CpuCount; + uint32_t CpuFrequency; + + uint8_t VendorString[12]; + uint8_t BrandString[48]; + + uint8_t MMX; + uint8_t SSE; + uint8_t SSE2; + uint8_t SSE3; + uint8_t SSE41; + uint8_t SSE42; + uint8_t AVX; + + uint32_t RamSize; + uint32_t RamFree; + uint32_t RamUsage; +}; + +int corinfo_GetInfo(struct corinfo* info); + +#ifdef __linux + #define __cpuid(cpu, command) \ + asm volatile \ + ("cpuid" : "=a" (cpu[0]), "=b" (cpu[1]), "=c" (cpu[2]), "=d" (cpu[3]) \ + : "a" (command), "c" (0)); +#endif + +static void __null_corinfo(struct corinfo* info); +static void __vendor_string(int cpu[4], uint8_t* string); +static void __brand_string(int cpu[4], uint8_t* string); +static void __extensions(int cpu[4], struct corinfo* info); + +#ifdef __linux + int corinfo_GetInfo(struct corinfo* info) + { + if (info == NULL) return -1; + __null_corinfo(info); + + struct sysinfo sys; + if (sysinfo(&sys) == -1) return -1; + + int cpu[4]; + __cpuid(cpu, 0x00000000); + __vendor_string(cpu, info->VendorString); + __brand_string(cpu, info->BrandString); + __extensions(cpu, info); + + info->CpuCount = sysconf(_SC_NPROCESSORS_ONLN); + + FILE* f = fopen("/proc/cpuinfo", "rb"); + if (f == NULL) return -1; + + char* line = NULL; + size_t line_length = 0; + size_t line_read = 0; + + while ((line_read = getline(&line, &line_length, f)) != -1) + { + if (memcmp(line, "cpu MHz", 7) == 0) + { + info->CpuFrequency = atoi(strchr(line, ':') + 2); + break; + } + } + + if (line) free(line); + + fclose(f); + + info->RamSize = sys.totalram / 1024; + info->RamFree = sys.freeram / 1024; + info->RamUsage = 100 - (info->RamFree / (float)info->RamSize) * 100; + + return 0; + } +#endif + + + +#ifdef _WIN32 + int corinfo_GetInfo(struct corinfo* info) + { + + } +#endif + + +void __null_corinfo(struct corinfo* info) +{ + info->CpuCount = 0; + info->CpuFrequency = 0; + + for (int i = 0; i < 12; i++) info->VendorString[i] = 0; + for (int i = 0; i < 48; i++) info->BrandString[i] = 0; + + info->MMX = 0; + info->SSE = 0; + info->SSE2 = 0; + info->SSE3 = 0; + info->SSE41 = 0; + info->SSE42 = 0; + info->AVX = 0; + + info->RamSize = 0; + info->RamFree = 0; + info->RamUsage = 0; +} + +void __vendor_string(int cpu[4], uint8_t* string) +{ + for (int i = 0; i < 4; i++) + { + string[i + 0] = (cpu[1] >> (i * 8)) & 0xFF; + string[i + 4] = (cpu[3] >> (i * 8)) & 0xFF; + string[i + 8] = (cpu[2] >> (i * 8)) & 0xFF; + } +} + +void __brand_string(int cpu[4], uint8_t* string) +{ + int commands[3] = { 0x80000002, 0x80000003, 0x80000004 }; + int offset = 0; + + for (int i = 0; i < 3; i++) + { + __cpuid(cpu, commands[i]); + for (int j = 0; j < 4; j++) + { + string[offset + j + 0] = (cpu[0] >> (j * 8)) & 0xFF; + string[offset + j + 4] = (cpu[1] >> (j * 8)) & 0xFF; + string[offset + j + 8] = (cpu[2] >> (j * 8)) & 0xFF; + string[offset + j + 12] = (cpu[3] >> (j * 8)) & 0xFF; + } + + offset += 16; + } +} + +void __extensions(int cpu[4], struct corinfo* info) +{ + __cpuid(cpu, 0x00000001); + info->MMX = (cpu[3] >> 23) & 0x1; + info->SSE = (cpu[3] >> 25) & 0x1; + info->SSE2 = (cpu[3] >> 26) & 0x1; + info->SSE3 = (cpu[2] >> 0) & 0x1; + info->SSE41 = (cpu[2] >> 19) & 0x1; + info->SSE42 = (cpu[2] >> 20) & 0x1; + info->AVX = (cpu[2] >> 28) & 0x1; +} + +#undef __cpuid + +#endif