mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
133 lines
4.4 KiB
C
133 lines
4.4 KiB
C
#include "cpucache.h"
|
|
#include "common/io.h"
|
|
#include "common/strutil.h"
|
|
|
|
static const char* parseCpuCacheIndex(FFstrbuf* path, FFCPUCacheResult* result, FFstrbuf* buffer, FFstrbuf* added) {
|
|
uint32_t baseLen = path->length;
|
|
ffStrbufAppendS(path, "/level");
|
|
if (!ffReadFileBuffer(path->chars, buffer)) {
|
|
return "ffReadFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/level\") == NULL";
|
|
}
|
|
|
|
uint32_t level = (uint32_t) ffStrbufToUInt(buffer, 0);
|
|
if (level < 1 || level > 4) {
|
|
return "level < 1 || level > 4";
|
|
}
|
|
|
|
ffStrbufSubstrBefore(path, baseLen);
|
|
ffStrbufAppendS(path, "/size");
|
|
if (!ffReadFileBuffer(path->chars, buffer)) {
|
|
return "ffReadFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/size\") == NULL";
|
|
}
|
|
|
|
uint32_t sizeKb = (uint32_t) ffStrbufToUInt(buffer, 0);
|
|
if (sizeKb == 0) {
|
|
return "size == 0";
|
|
}
|
|
|
|
ffStrbufSubstrBefore(path, baseLen);
|
|
ffStrbufAppendS(path, "/type");
|
|
if (!ffReadFileBuffer(path->chars, buffer)) {
|
|
return "ffReadFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/type\") == NULL";
|
|
}
|
|
ffStrbufTrimRightSpace(buffer);
|
|
|
|
FFCPUCacheType cacheType = 0;
|
|
switch (buffer->chars[0]) {
|
|
case 'I':
|
|
cacheType = FF_CPU_CACHE_TYPE_INSTRUCTION;
|
|
break;
|
|
case 'D':
|
|
cacheType = FF_CPU_CACHE_TYPE_DATA;
|
|
break;
|
|
case 'U':
|
|
cacheType = FF_CPU_CACHE_TYPE_UNIFIED;
|
|
break;
|
|
case 'T':
|
|
cacheType = FF_CPU_CACHE_TYPE_TRACE;
|
|
break;
|
|
default:
|
|
return "unknown cache type";
|
|
}
|
|
|
|
uint32_t lineSize = 0;
|
|
ffStrbufSubstrBefore(path, baseLen);
|
|
ffStrbufAppendS(path, "/coherency_line_size");
|
|
if (ffReadFileBuffer(path->chars, buffer)) {
|
|
lineSize = (uint32_t) ffStrbufToUInt(buffer, 0);
|
|
}
|
|
|
|
ffStrbufSubstrBefore(path, baseLen);
|
|
ffStrbufAppendS(path, "/shared_cpu_list");
|
|
ffStrbufClear(buffer);
|
|
ffStrbufAppendC(buffer, '[');
|
|
if (!ffAppendFileBuffer(path->chars, buffer)) {
|
|
return "ffAppendFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/shared_cpu_list\") == NULL";
|
|
}
|
|
ffStrbufTrimRightSpace(buffer);
|
|
|
|
// deduplicate shared caches
|
|
ffStrbufAppendF(buffer, "_%u_%u_%u_%u]", level, sizeKb, lineSize, cacheType);
|
|
|
|
if (ffStrbufContain(added, buffer)) {
|
|
return NULL;
|
|
}
|
|
ffStrbufAppend(added, buffer);
|
|
ffCPUCacheAddItem(result, level, sizeKb * 1024, lineSize, cacheType);
|
|
return NULL;
|
|
}
|
|
|
|
static const char* parseCpuCache(FFstrbuf* path, FFCPUCacheResult* result, FFstrbuf* buffer, FFstrbuf* added) {
|
|
ffStrbufAppendS(path, "/cache/");
|
|
uint32_t baseLen = path->length;
|
|
FF_AUTO_CLOSE_DIR DIR* pathCacheDir = opendir(path->chars);
|
|
if (!pathCacheDir) {
|
|
return "opendir(\"/sys/devices/system/cpu/cpuX/cache/\") == NULL";
|
|
}
|
|
|
|
struct dirent* pathCacheEntry;
|
|
while ((pathCacheEntry = readdir(pathCacheDir)) != NULL) {
|
|
if (!ffStrStartsWith(pathCacheEntry->d_name, "index") || !ffCharIsDigit(pathCacheEntry->d_name[strlen("index")])) {
|
|
continue;
|
|
}
|
|
|
|
ffStrbufAppendS(path, pathCacheEntry->d_name);
|
|
const char* error = parseCpuCacheIndex(path, result, buffer, added);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
ffStrbufSubstrBefore(path, baseLen);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char* ffDetectCPUCache(FFCPUCacheResult* result) {
|
|
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu
|
|
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/");
|
|
uint32_t baseLen = path.length;
|
|
FF_AUTO_CLOSE_DIR DIR* pathCpuDir = opendir(path.chars);
|
|
if (!pathCpuDir) {
|
|
return "opendir(\"/sys/devices/system/cpu/\") == NULL";
|
|
}
|
|
|
|
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
|
FF_STRBUF_AUTO_DESTROY added = ffStrbufCreate();
|
|
|
|
struct dirent* pathCpuEntry;
|
|
while ((pathCpuEntry = readdir(pathCpuDir)) != NULL) {
|
|
if (!ffStrStartsWith(pathCpuEntry->d_name, "cpu") ||
|
|
!ffCharIsDigit(pathCpuEntry->d_name[strlen("cpu")])) {
|
|
continue;
|
|
}
|
|
|
|
ffStrbufAppendS(&path, pathCpuEntry->d_name);
|
|
const char* error = parseCpuCache(&path, result, &buffer, &added);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
ffStrbufSubstrBefore(&path, baseLen);
|
|
}
|
|
return NULL;
|
|
}
|