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-03-29 09:28:49 +08:00
|
|
|
char* token = NULL;
|
2026-06-27 17:18:19 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "MemTotal:", strlen("MemTotal:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
memTotal = (uint64_t) strtoull(token + strlen("MemTotal:"), NULL, 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-06-27 17:18:19 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "MemAvailable:", strlen("MemAvailable:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
memAvailable = (uint64_t) strtoull(token + strlen("MemAvailable:"), NULL, 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
|
|
|
|
|
if ((token = memmem(buf, (size_t) nRead, "MemFree:", strlen("MemFree:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
memFree = (uint64_t) strtoull(token + strlen("MemFree:"), NULL, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-06-27 17:18:19 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "Buffers:", strlen("Buffers:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
buffers = (uint64_t) strtoull(token + strlen("Buffers:"), NULL, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-06-27 17:18:19 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "Cached:", strlen("Cached:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
cached = (uint64_t) strtoull(token + strlen("Cached:"), NULL, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-06-27 17:18:19 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "Shmem:", strlen("Shmem:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
shmem = (uint64_t) strtoull(token + strlen("Shmem:"), NULL, 10);
|
2026-03-29 09:28:49 +08:00
|
|
|
}
|
2023-12-07 16:30:10 +08:00
|
|
|
|
2026-06-27 17:18:19 +08:00
|
|
|
if ((token = memmem(buf, (size_t) nRead, "SReclaimable:", strlen("SReclaimable:"))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
sReclaimable = (uint64_t) strtoull(token + strlen("SReclaimable:"), NULL, 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);
|
|
|
|
|
if (__builtin_expect(p != NULL, true)) {
|
|
|
|
|
++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"));
|
|
|
|
|
if (__builtin_expect(pData != NULL, true)) {
|
|
|
|
|
uint32_t dataOffset = (uint32_t) (pData - p);
|
|
|
|
|
p += dataOffset + strlen("data\n");
|
|
|
|
|
nRead -= (ssize_t) (dataOffset + strlen("data\n"));
|
|
|
|
|
assert(nRead > 0);
|
|
|
|
|
|
|
|
|
|
if ((token = memmem(p, (size_t) nRead, "\nsize ", strlen("\nsize "))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
arcSize = (uint64_t) strtoull(token + 1 + dataOffset, NULL, 10);
|
2026-06-27 17:18:19 +08:00
|
|
|
if (arcSize > 0) {
|
|
|
|
|
uint64_t arcMin = 0;
|
|
|
|
|
if ((token = memmem(p, (size_t) nRead, "\nc_min ", strlen("\nc_min "))) != NULL) {
|
2026-06-28 15:21:05 +08:00
|
|
|
arcMin = (uint64_t) strtoull(token + 1 + dataOffset, NULL, 10);
|
2026-06-27 17:18:19 +08:00
|
|
|
if (arcSize > arcMin) {
|
|
|
|
|
arcSize -= arcMin;
|
|
|
|
|
if (ram->bytesUsed > arcSize) {
|
|
|
|
|
ram->bytesUsed -= arcSize;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-11 20:39:54 +08:00
|
|
|
return NULL;
|
2022-09-05 10:57:09 +02:00
|
|
|
}
|