2022-09-05 10:57:09 +02:00
|
|
|
#include "memory.h"
|
2026-01-06 09:48:38 +08:00
|
|
|
#include "common/io.h"
|
2022-09-05 10:57:09 +02:00
|
|
|
|
2026-03-29 09:28:49 +08:00
|
|
|
const char* ffDetectMemory(FFMemoryResult* ram) {
|
2023-12-04 16:47:00 +09:00
|
|
|
char buf[PROC_FILE_BUFFSIZ];
|
2024-10-18 16:15:48 +08:00
|
|
|
ssize_t nRead = ffReadFileData("/proc/meminfo", ARRAY_SIZE(buf) - 1, buf);
|
2026-03-29 09:28:49 +08:00
|
|
|
if (nRead < 0) {
|
2024-10-18 16:15:48 +08:00
|
|
|
return "ffReadFileData(\"/proc/meminfo\", ARRAY_SIZE(buf)-1, buf)";
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-04 16:47:00 +09:00
|
|
|
buf[nRead] = '\0';
|
2022-09-05 10:57:09 +02:00
|
|
|
|
2023-11-24 10:12:34 +08:00
|
|
|
uint64_t memTotal = 0,
|
2023-12-07 16:30:10 +08:00
|
|
|
memAvailable = 0,
|
2022-09-05 10:57:09 +02:00
|
|
|
shmem = 0,
|
|
|
|
|
memFree = 0,
|
|
|
|
|
buffers = 0,
|
|
|
|
|
cached = 0,
|
2022-10-18 23:46:42 +08:00
|
|
|
sReclaimable = 0;
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
char* token = nullptr;
|
|
|
|
|
if ((token = memmem(buf, (size_t) nRead, "MemTotal:", strlen("MemTotal:"))) != nullptr) {
|
|
|
|
|
memTotal = (uint64_t) strtoull(token + strlen("MemTotal:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
} else {
|
2023-12-07 16:30:10 +08:00
|
|
|
return "MemTotal not found in /proc/meminfo";
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "MemAvailable:", strlen("MemAvailable:"))) != nullptr) {
|
|
|
|
|
memAvailable = (uint64_t) strtoull(token + strlen("MemAvailable:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2026-06-27 17:18:19 +08:00
|
|
|
|
|
|
|
|
if (memAvailable == 0 || memAvailable >= memTotal) { // MemAvailable can be unreasonable. #1988
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "MemFree:", strlen("MemFree:"))) != nullptr) {
|
|
|
|
|
memFree = (uint64_t) strtoull(token + strlen("MemFree:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "Buffers:", strlen("Buffers:"))) != nullptr) {
|
|
|
|
|
buffers = (uint64_t) strtoull(token + strlen("Buffers:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "Cached:", strlen("Cached:"))) != nullptr) {
|
|
|
|
|
cached = (uint64_t) strtoull(token + strlen("Cached:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "Shmem:", strlen("Shmem:"))) != nullptr) {
|
|
|
|
|
shmem = (uint64_t) strtoull(token + strlen("Shmem:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "SReclaimable:", strlen("SReclaimable:"))) != nullptr) {
|
|
|
|
|
sReclaimable = (uint64_t) strtoull(token + strlen("SReclaimable:"), nullptr, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-04 16:47:00 +09:00
|
|
|
|
2023-12-07 16:30:10 +08:00
|
|
|
memAvailable = memFree + buffers + cached + sReclaimable - shmem;
|
|
|
|
|
}
|
2022-09-05 10:57:09 +02:00
|
|
|
|
2023-11-24 10:12:34 +08:00
|
|
|
ram->bytesTotal = memTotal * 1024lu;
|
2023-12-07 16:30:10 +08:00
|
|
|
ram->bytesUsed = (memTotal - memAvailable) * 1024lu;
|
2023-05-11 20:39:54 +08:00
|
|
|
|
2026-06-27 17:18:19 +08:00
|
|
|
uint64_t arcSize = 0;
|
|
|
|
|
nRead = ffReadFileData("/proc/spl/kstat/zfs/arcstats", ARRAY_SIZE(buf) - 1, buf);
|
|
|
|
|
if (nRead > 0) {
|
|
|
|
|
buf[nRead] = '\0';
|
|
|
|
|
// 24 1 0x01 148 40256 2053603602 851614020716
|
|
|
|
|
// name type data
|
|
|
|
|
// hits 4 752
|
|
|
|
|
|
|
|
|
|
// Skip first line
|
|
|
|
|
const char* p = memchr(buf, '\n', (size_t) nRead);
|
2026-07-10 18:08:04 +08:00
|
|
|
if (__builtin_expect(p != nullptr, true)) {
|
2026-06-27 17:18:19 +08:00
|
|
|
++p;
|
|
|
|
|
nRead -= (p - buf);
|
|
|
|
|
assert(nRead > 0);
|
|
|
|
|
|
|
|
|
|
// Find line offset of data
|
|
|
|
|
const char* pData = memmem(p, (size_t) nRead, "data\n", strlen("data\n"));
|
2026-07-10 18:08:04 +08:00
|
|
|
if (__builtin_expect(pData != nullptr, true)) {
|
2026-06-27 17:18:19 +08:00
|
|
|
uint32_t dataOffset = (uint32_t) (pData - p);
|
|
|
|
|
p += dataOffset + strlen("data\n");
|
|
|
|
|
nRead -= (ssize_t) (dataOffset + strlen("data\n"));
|
|
|
|
|
assert(nRead > 0);
|
|
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(p, (size_t) nRead, "\nsize ", strlen("\nsize "))) != nullptr) {
|
|
|
|
|
arcSize = (uint64_t) strtoull(token + 1 + dataOffset, nullptr, 10);
|
2026-06-27 17:18:19 +08:00
|
|
|
if (arcSize > 0) {
|
|
|
|
|
uint64_t arcMin = 0;
|
2026-07-10 18:08:04 +08:00
|
|
|
if ((token = memmem(p, (size_t) nRead, "\nc_min ", strlen("\nc_min "))) != nullptr) {
|
|
|
|
|
arcMin = (uint64_t) strtoull(token + 1 + dataOffset, nullptr, 10);
|
2026-06-27 17:18:19 +08:00
|
|
|
if (arcSize > arcMin) {
|
|
|
|
|
arcSize -= arcMin;
|
|
|
|
|
if (ram->bytesUsed > arcSize) {
|
|
|
|
|
ram->bytesUsed -= arcSize;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-10 18:08:04 +08:00
|
|
|
return nullptr;
|
2022-09-05 10:57:09 +02:00
|
|
|
}
|