Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions man/i3status.man
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,8 @@ starting from %cpu0. This feature is currently not supported in FreeBSD.

=== 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
Expand All @@ -487,17 +487,16 @@ If the +format_degraded+ parameter is given and either the critical or the
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)

Expand Down
60 changes: 55 additions & 5 deletions src/print_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@
#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
#define STRING_SIZE ((sizeof "1023. TiB") + MAX_DECIMALS)

#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.
*
Expand All @@ -42,7 +47,7 @@ static int print_percentage(char *outwalk, float percent) {
}
#endif

#if defined(__linux__)
#if defined(__linux__) || defined(__OpenBSD__)
/*
* Convert a string to its absolute representation based on the total
* memory of `mem_total`.
Expand Down Expand Up @@ -89,18 +94,62 @@ static unsigned long memory_absolute(const char *mem_amount, const unsigned long
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;
unsigned long ram_buffers;
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;
Expand Down Expand Up @@ -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")) {
Expand Down