[hackers] [slstatus] more concise memory calculation on Linux || drkhsh

From: <git_AT_suckless.org>
Date: Thu, 24 Jul 2025 22:51:59 +0200 (CEST)

commit 8723e8b8c69c08bae8abe02ea1f4a49758b8bdfc
Author: drkhsh <me_AT_drkhsh.at>
AuthorDate: Thu Jul 24 22:41:25 2025 +0200
Commit: drkhsh <me_AT_drkhsh.at>
CommitDate: Thu Jul 24 22:41:25 2025 +0200

    more concise memory calculation on Linux
    
    more flexible parsing for /proc/meminfo to take shared and reclaimable
    memory into account. this matches the output with free(1).
    
    additionally this could fix some corner cases, as the order of fields in
    /proc/meminfo is not strictly defined.
    
    slstatus:
    percent 81% free 2.5 Gi total 23.4 Gi used 19.0 Gi
    
    free(1):
                   total used free shared buff/cache available
    Mem: 23Gi 19Gi 2.5Gi 1.3Gi 3.2Gi 3.6Gi

diff --git a/components/ram.c b/components/ram.c
index 15c4b74..bf71dcf 100644
--- a/components/ram.c
+++ b/components/ram.c
_AT_@ -11,36 +11,45 @@
         ram_free(const char *unused)
         {
                 uintmax_t free;
+ FILE *fp;
 
- if (pscanf("/proc/meminfo",
- "MemTotal: %ju kB\n"
- "MemFree: %ju kB\n"
- "MemAvailable: %ju kB\n",
- &free, &free, &free) != 3)
+ if (!(fp = fopen("/proc/meminfo", "r")))
                         return NULL;
 
+ if (lscanf(fp, "MemFree:", "%ju kB", &free) != 1) {
+ fclose(fp);
+ return NULL;
+ }
+
+ fclose(fp);
                 return fmt_human(free * 1024, 1024);
         }
 
         const char *
         ram_perc(const char *unused)
         {
- uintmax_t total, free, buffers, cached;
+ uintmax_t total, free, buffers, cached, shmem, sreclaimable;
                 int percent;
+ FILE *fp;
+
+ if (!(fp = fopen("/proc/meminfo", "r")))
+ return NULL;
 
- if (pscanf("/proc/meminfo",
- "MemTotal: %ju kB\n"
- "MemFree: %ju kB\n"
- "MemAvailable: %ju kB\n"
- "Buffers: %ju kB\n"
- "Cached: %ju kB\n",
- &total, &free, &buffers, &buffers, &cached) != 5)
+ if (lscanf(fp, "MemTotal:", "%ju kB", &total) != 1 ||
+ lscanf(fp, "MemFree:", "%ju kB", &free) != 1 ||
+ lscanf(fp, "Buffers:", "%ju kB", &buffers) != 1 ||
+ lscanf(fp, "Cached:", "%ju kB", &cached) != 1 ||
+ lscanf(fp, "Shmem:", "%ju kB", &shmem) != 1 ||
+ lscanf(fp, "SReclaimable:", "%ju kB", &sreclaimable) != 1) {
+ fclose(fp);
                         return NULL;
+ }
+ fclose(fp);
 
                 if (total == 0)
                         return NULL;
 
- percent = 100 * ((total - free) - (buffers + cached)) / total;
+ percent = 100 * (total - free - buffers - cached - sreclaimable + shmem) / total;
                 return bprintf("%d", percent);
         }
 
_AT_@ -59,18 +68,24 @@
         const char *
         ram_used(const char *unused)
         {
- uintmax_t total, free, buffers, cached, used;
+ uintmax_t total, free, buffers, cached, used, shmem, sreclaimable;
+ FILE *fp;
+
+ if (!(fp = fopen("/proc/meminfo", "r")))
+ return NULL;
 
- if (pscanf("/proc/meminfo",
- "MemTotal: %ju kB\n"
- "MemFree: %ju kB\n"
- "MemAvailable: %ju kB\n"
- "Buffers: %ju kB\n"
- "Cached: %ju kB\n",
- &total, &free, &buffers, &buffers, &cached) != 5)
+ if (lscanf(fp, "MemTotal:", "%ju kB", &total) != 1 ||
+ lscanf(fp, "MemFree:", "%ju kB", &free) != 1 ||
+ lscanf(fp, "Buffers:", "%ju kB", &buffers) != 1 ||
+ lscanf(fp, "Cached:", "%ju kB", &cached) != 1 ||
+ lscanf(fp, "Shmem:", "%ju kB", &shmem) != 1 ||
+ lscanf(fp, "SReclaimable:", "%ju kB", &sreclaimable) != 1) {
+ fclose(fp);
                         return NULL;
+ }
+ fclose(fp);
 
- used = (total - free - buffers - cached);
+ used = total - free - buffers - cached - sreclaimable + shmem;
                 return fmt_human(used * 1024, 1024);
         }
 #elif defined(__OpenBSD__)
diff --git a/util.c b/util.c
index bca9b2e..d33cf9d 100644
--- a/util.c
+++ b/util.c
_AT_@ -139,3 +139,20 @@ pscanf(const char *path, const char *fmt, ...)
 
         return (n == EOF) ? -1 : n;
 }
+
+int
+lscanf(FILE *fp, const char *key, const char *fmt, void *res)
+{
+ int n;
+ char line[256];
+
+ n = -1;
+ while (fgets(line, sizeof(line), fp))
+ if (strncmp(line, key, strlen(key)) == 0) {
+ n = sscanf(line + strlen(key), fmt, res);
+ break;
+ }
+
+ rewind(fp);
+ return (n == 1) ? 1 : -1;
+}
diff --git a/util.h b/util.h
index cf4b027..7a960aa 100644
--- a/util.h
+++ b/util.h
_AT_@ -1,5 +1,6 @@
 /* See LICENSE file for copyright and license details. */
 #include <stdint.h>
+#include <stdio.h>
 
 extern char buf[1024];
 
_AT_@ -14,3 +15,4 @@ int esnprintf(char *str, size_t size, const char *fmt, ...);
 const char *bprintf(const char *fmt, ...);
 const char *fmt_human(uintmax_t num, int base);
 int pscanf(const char *path, const char *fmt, ...);
+int lscanf(FILE *fp, const char *key, const char *fmt, void *res);
Received on Thu Jul 24 2025 - 22:51:59 CEST

This archive was generated by hypermail 2.3.0 : Thu Jul 24 2025 - 23:00:37 CEST