Download raw body.
Patch: x11/i3status
On Wed, Nov 05, 2025 at 09:28:42AM -0800, Kristaps Dzonsons wrote:
> 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.
Working well for me on amd64. Thanks!
> 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 <stdlib.h>
> #include <yajl/yajl_gen.h>
> #include <yajl/yajl_version.h>
> +#ifdef __OpenBSD__
> +# include <sys/mount.h>
> +# include <sys/shm.h>
> +# include <sys/sysctl.h>
> +#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)
>
Patch: x11/i3status