From: Kristaps Dzonsons Subject: Patch: x11/i3status To: "ports@openbsd.org" Date: Wed, 5 Nov 2025 09:28:42 -0800 Hi all, the i3status port didn't include memory information, so I added it in. Enclosed is a patch for the memory and additional documentation in the manpage. The calculation for used/available memory is a little different than on Linux: total = (usermem from sysctl) free = (from sysctl) cached = (from sysctl) buffers = shared = 0 available = free + cached used (memavailable) = total - available used (classical) = total - free - buffers - cached shared = 0 So both methods of used memory are equivalent. These are already in an upstream PR. Best, Kristaps Index: src/print_mem.c --- src/print_mem.c.orig +++ src/print_mem.c @@ -5,6 +5,11 @@ #include #include #include +#ifdef __OpenBSD__ +# include +# include +# include +#endif #include "i3status.h" #define MAX_DECIMALS 4 @@ -12,12 +17,12 @@ #define BINARY_BASE 1024UL -#if defined(__linux__) +#if defined(__linux__) || defined(__OpenBSD__) static const char *const iec_symbols[] = {"B", "KiB", "MiB", "GiB", "TiB"}; #define MAX_EXPONENT ((sizeof iec_symbols / sizeof *iec_symbols) - 1) #endif -#if defined(__linux__) +#if defined(__linux__) || defined(__OpenBSD__) /* * Prints the given amount of bytes in a human readable manner. * @@ -42,7 +47,7 @@ static int print_percentage(char *outwalk, float perce } #endif -#if defined(__linux__) +#if defined(__linux__) || defined(__OpenBSD__) /* * Convert a string to its absolute representation based on the total * memory of `mem_total`. @@ -89,11 +94,10 @@ static unsigned long memory_absolute(const char *mem_a void print_memory(memory_ctx_t *ctx) { char *outwalk = ctx->buf; -#if defined(__linux__) +#if defined(__linux__) || defined(__OpenBSD__) const char *selected_format = ctx->format; const char *output_color = NULL; - int unread_fields = 6; unsigned long ram_total; unsigned long ram_free; unsigned long ram_available; @@ -101,6 +105,51 @@ void print_memory(memory_ctx_t *ctx) { unsigned long ram_cached; unsigned long ram_shared; +#if defined(__OpenBSD__) + int64_t tmp; + size_t sz; + + /* Total memory set to the physical memory less kernel. */ + + int usermem_mib[] = {CTL_HW, HW_USERMEM64}; + sz = sizeof(tmp); + if (sysctl(usermem_mib, 2, &tmp, &sz, NULL, 0) != 0) { + goto error; + } + ram_total = tmp; + + int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; + struct uvmexp uvmexp; + sz = sizeof(uvmexp); + if (sysctl(uvmexp_mib, 2, &uvmexp, &sz, NULL, 0) == -1) { + goto error; + } + const long pagesize = sysconf(_SC_PAGESIZE); + ram_free = uvmexp.free * pagesize; + + int shmall_mib[] = {CTL_KERN, KERN_SHMINFO, KERN_SHMINFO_SHMALL}; + sz = sizeof(tmp); + if (sysctl(shmall_mib, 3, &tmp, &sz, NULL, 0) == -1) { + goto error; + } + + int bcstats_mib[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT}; + struct bcachestats bcstats; + sz = sizeof(bcstats); + if (sysctl(bcstats_mib, 3, &bcstats, &sz, NULL, 0) == -1) { + goto error; + } + ram_cached = bcstats.numbufpages * pagesize; + + /* Available is free and cached memory. */ + + ram_available = ram_free + ram_cached; + + /* This information doesn't seem to exist. */ + + ram_shared = ram_buffers = 0; +#elif defined(__linux__) + int unread_fields = 6; FILE *file = fopen("/proc/meminfo", "r"); if (!file) { goto error; @@ -138,6 +187,7 @@ void print_memory(memory_ctx_t *ctx) { ram_buffers *= 1024UL; ram_cached *= 1024UL; ram_shared *= 1024UL; +#endif unsigned long ram_used; if (BEGINS_WITH(ctx->memory_used_method, "memavailable")) { Index: man/i3status.man --- man/i3status.man.orig +++ man/i3status.man @@ -469,8 +469,8 @@ starting from %cpu0. This feature is currently not sup === Memory -Gets the memory usage from system on a Linux system from +/proc/meminfo+. Other -systems are currently not supported. +Gets the memory usage from +/proc/meminfo+ on a Linux system and +sysctl+ on +OpenBSD. Other systems are currently not supported. As format placeholders, +total+, +used+, +free+, +available+ and +shared+ are available. These will print human readable values. It's also possible to prefix @@ -487,17 +487,16 @@ If the +format_degraded+ parameter is given and either degraded threshold applies, +format_degraded+ will get used as format string. It acts equivalently to +format+. -It's also possible to define the unit for the various format placeholders. As -+/proc/meminfo+ returns the memory in kB they will be converted to the given -unit. If no unit is given or the +auto+ option is used, the conversion will -select the maximum possible unit. +It's also possible to define the unit for the various format placeholders. +If no unit is given or the +auto+ option is used, the conversion will select the +maximum possible unit. As the converted format placeholder will be a decimal number, the number of decimals can be configured via the +decimals+ option. If no such option is given the converted format placeholder will have one decimal. As Linux' meminfo doesn't expose the overall memory in use, there are multiple -methods to distinguish the actually used memory. +methods to distinguish the actually used memory. On OpenBSD, these are the same. *Example memory_used_method*: +memavailable+ ("total memory" - "MemAvailable", matches +free+ command)