From: Josh Grosse Subject: Re: Patch: x11/i3status To: ports@openbsd.org Date: Wed, 5 Nov 2025 17:54:58 -0500 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 > #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) >