2018-12-26 13:46:04 -05:00
|
|
|
/* $Id: get_mem.c,v 1.5 2018/12/26 18:46:04 bch Exp $
|
2020-11-17 12:14:24 -05:00
|
|
|
*
|
|
|
|
* xmem(1) utility adapted by Christian Barthel <bch@online.de>:
|
|
|
|
* - Added OpenBSD support
|
|
|
|
* - Added FreeBSD support
|
2017-02-18 16:06:47 -05:00
|
|
|
*
|
2017-02-18 16:03:44 -05:00
|
|
|
* get memory usage, from get_load.c derived
|
|
|
|
*
|
|
|
|
* Author: Hans-Helmut Buehmann 20. Jan. 1996
|
2020-11-17 12:14:24 -05:00
|
|
|
*
|
2017-02-18 16:03:44 -05:00
|
|
|
* Modified for more recent kernels Helmut Geyer Oct. 1996
|
|
|
|
*/
|
|
|
|
|
2020-11-17 12:14:24 -05:00
|
|
|
#if __OpenBSD__
|
2018-12-26 13:46:04 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
#include <sys/param.h> /* DEV_BSIZE MAXCOMLEN PZERO */
|
2017-02-18 16:06:47 -05:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/swap.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/proc.h>
|
2017-02-26 11:03:48 -05:00
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2017-02-18 16:03:44 -05:00
|
|
|
#include <X11/Xos.h>
|
|
|
|
#include <X11/Intrinsic.h>
|
|
|
|
#include <stdio.h>
|
2017-02-18 16:06:47 -05:00
|
|
|
#include <stdlib.h>
|
2017-02-26 11:03:48 -05:00
|
|
|
#include <err.h>
|
2017-02-18 16:03:44 -05:00
|
|
|
#include "MemStripChart.h"
|
|
|
|
|
2020-11-17 12:14:24 -05:00
|
|
|
static int pageshift = -1;
|
2017-02-18 16:06:47 -05:00
|
|
|
#define pagetok(size) ((size) << pageshift)
|
2020-11-17 12:14:24 -05:00
|
|
|
#define LOG1024 10
|
2017-02-18 16:06:47 -05:00
|
|
|
|
2020-11-17 12:14:24 -05:00
|
|
|
static double allmem_kb = 0;
|
2017-02-18 16:06:47 -05:00
|
|
|
|
|
|
|
static void initPageShift(void)
|
|
|
|
{
|
2022-01-08 02:28:15 -05:00
|
|
|
int pagesize = getpagesize();
|
|
|
|
pageshift = 0;
|
|
|
|
while (pagesize > 1) {
|
|
|
|
pageshift++;
|
|
|
|
pagesize >>= 1;
|
|
|
|
}
|
|
|
|
pageshift -= LOG1024;
|
2017-02-18 16:06:47 -05:00
|
|
|
}
|
|
|
|
|
2020-11-17 12:14:24 -05:00
|
|
|
static double getSwapFrac()
|
2017-02-18 16:06:47 -05:00
|
|
|
{
|
2022-01-08 02:28:15 -05:00
|
|
|
struct swapent *swdev;
|
|
|
|
int used, total, nswap, rnswap, i;
|
|
|
|
|
|
|
|
nswap = swapctl(SWAP_NSWAP, 0, 0);
|
|
|
|
if (nswap == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
swdev = calloc(nswap, sizeof(*swdev));
|
|
|
|
if (swdev == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
rnswap = swapctl(SWAP_STATS, swdev, nswap);
|
|
|
|
if (rnswap == -1) {
|
|
|
|
free(swdev);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if rnswap != nswap, then what? */
|
|
|
|
|
|
|
|
/* Total things up */
|
|
|
|
total = used = 0;
|
|
|
|
for (i = 0; i < nswap; i++) {
|
|
|
|
if (swdev[i].se_flags & SWF_ENABLE) {
|
|
|
|
used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
|
|
|
|
total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(swdev);
|
|
|
|
return (double)used/total;
|
2017-02-18 16:06:47 -05:00
|
|
|
}
|
|
|
|
|
2020-11-17 12:14:24 -05:00
|
|
|
void GetMemLoadPoint(Widget w, caddr_t closure, caddr_t call_data)
|
2017-02-18 16:03:44 -05:00
|
|
|
{
|
2022-01-08 02:28:15 -05:00
|
|
|
static int bcstats_mib[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT};
|
|
|
|
static int uvmexp_mib[] = {CTL_VM, VM_UVMEXP};
|
|
|
|
MemStripChartCallbackData ret;
|
|
|
|
struct uvmexp uvmexp;
|
|
|
|
struct bcachestats bcstats;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
if (pageshift < 0)
|
|
|
|
initPageShift();
|
|
|
|
|
|
|
|
size = sizeof(uvmexp);
|
|
|
|
if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) {
|
|
|
|
warn("sysctl failed");
|
|
|
|
bzero(&uvmexp, sizeof(uvmexp));
|
|
|
|
}
|
|
|
|
size = sizeof(bcstats);
|
|
|
|
if (sysctl(bcstats_mib, 3, &bcstats, &size, NULL, 0) < 0) {
|
|
|
|
warn("sysctl failed");
|
|
|
|
bzero(&bcstats, sizeof(bcstats));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
allmem_kb = pagetok(uvmexp.npages);
|
|
|
|
ret.cached = pagetok(bcstats.numbufpages) / allmem_kb;
|
|
|
|
ret.free = pagetok(uvmexp.free) / allmem_kb;
|
|
|
|
ret.buffer = 0;
|
|
|
|
ret.code = (1 - ret.cached - ret.free);
|
|
|
|
ret.swap = getSwapFrac();
|
2017-02-18 16:03:44 -05:00
|
|
|
|
2017-02-18 16:06:47 -05:00
|
|
|
#ifdef DEBUG
|
2022-01-08 02:28:15 -05:00
|
|
|
printf("%lf %lf %lf %lf %lf\n",
|
|
|
|
allmem_kb,
|
|
|
|
ret.code,
|
|
|
|
ret.cached,
|
|
|
|
ret.free,
|
|
|
|
ret.swap);
|
2020-11-17 12:14:24 -05:00
|
|
|
#endif
|
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
memcpy(call_data, &ret, sizeof(MemStripChartCallbackData));
|
2020-11-17 12:14:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#if __FreeBSD__
|
|
|
|
|
|
|
|
/* $Id: get_mem_fbsd.c,v 1.1 2018/12/26 18:46:16 bch Exp $
|
|
|
|
*
|
|
|
|
* Author: Christian Barthel <bch@online.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
#include <sys/types.h> /* DEV_BSIZE MAXCOMLEN PZERO */
|
2020-11-17 12:14:24 -05:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <kvm.h>
|
|
|
|
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
#include <X11/Intrinsic.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include "MemStripChart.h"
|
|
|
|
|
|
|
|
static int pageshift = -1;
|
|
|
|
static int pagesize = 0;
|
|
|
|
static kvm_t *kd = 0;
|
|
|
|
#define pagetok(size) ((size) << pageshift)
|
|
|
|
#define LOG1024 10
|
|
|
|
|
|
|
|
static unsigned int allmem_pages = 0;
|
|
|
|
|
|
|
|
static void initPageShift(void)
|
|
|
|
{
|
2022-01-08 02:28:15 -05:00
|
|
|
pagesize = getpagesize();
|
|
|
|
size_t len = sizeof(allmem_pages);
|
|
|
|
int mib[len];
|
|
|
|
pageshift = 0;
|
|
|
|
while (pagesize > 1) {
|
|
|
|
pageshift++;
|
|
|
|
pagesize >>= 1;
|
|
|
|
}
|
|
|
|
pageshift -= LOG1024;
|
|
|
|
|
|
|
|
kd = kvm_open(NULL, "/dev/null" ,NULL, O_RDONLY, "kvm_open");
|
|
|
|
|
|
|
|
if (sysctlbyname("vm.stats.vm.v_page_count", &allmem_pages, &len, NULL, 0) == -1)
|
|
|
|
perror("sysctl");
|
2020-11-17 12:14:24 -05:00
|
|
|
#ifdef DEBUG
|
2022-01-08 02:28:15 -05:00
|
|
|
printf("page_count: %d\n", allmem_pages);
|
2020-11-17 12:14:24 -05:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static double getSwapFrac()
|
|
|
|
{
|
2022-01-08 02:28:15 -05:00
|
|
|
/* XXX Borrowed from top(1) code: */
|
|
|
|
int n;
|
|
|
|
struct kvm_swap swapary[1];
|
|
|
|
static int pagesize = 0;
|
|
|
|
static unsigned long swap_maxpages = 0;
|
|
|
|
size_t sz = sizeof(swap_maxpages);
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
int retavail = 0;
|
|
|
|
int retfree = 0;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
n = kvm_getswapinfo(kd, swapary, 1, 0);
|
|
|
|
if (n < 0 || swapary[0].ksw_total == 0)
|
|
|
|
return (0);
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
if (swap_maxpages == 0)
|
|
|
|
sysctlbyname("vm.swap_maxpages",
|
|
|
|
&swap_maxpages, &sz, NULL, 0);
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
if ( swapary[0].ksw_total > swap_maxpages )
|
|
|
|
swapary[0].ksw_total = swap_maxpages;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
retavail = swapary[0].ksw_total;
|
|
|
|
retfree = swapary[0].ksw_total - swapary[0].ksw_used;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2022-01-08 02:28:15 -05:00
|
|
|
printf("swap: %d %d %d %d\n", retavail,
|
|
|
|
retavail, swapary[0].ksw_total,
|
|
|
|
swapary[0].ksw_used);
|
2020-11-17 12:14:24 -05:00
|
|
|
#endif
|
2022-01-08 02:28:15 -05:00
|
|
|
return (double)(retavail-retfree)/(double)retavail;
|
2020-11-17 12:14:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void GetMemLoadPoint(Widget w, caddr_t closure, caddr_t call_data)
|
|
|
|
{
|
2022-01-08 02:28:15 -05:00
|
|
|
MemStripChartCallbackData ret;
|
|
|
|
int a, b;
|
|
|
|
size_t sz = sizeof(int);
|
|
|
|
double cache = 0;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
if (pageshift < 0)
|
|
|
|
initPageShift();
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
sysctlbyname("vm.stats.vm.v_wire_count", &a, &sz, NULL, 0);
|
|
|
|
ret.code = (double)a / (double)allmem_pages;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
sysctlbyname("vm.stats.vm.v_active_count", &a, &sz, NULL, 0);
|
|
|
|
ret.buffer = (double)a / (double)allmem_pages;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
/* v_cache_count and v_inactive_count are treated similarly */
|
|
|
|
sysctlbyname("vm.stats.vm.v_inactive_count", &a, &sz, NULL, 0);
|
|
|
|
sysctlbyname("vm.stats.vm.v_cache_count", &b, &sz, NULL, 0);
|
|
|
|
ret.cached = (double)(a + b) / allmem_pages;
|
2020-11-17 12:14:24 -05:00
|
|
|
|
|
|
|
|
2022-01-08 02:28:15 -05:00
|
|
|
sysctlbyname("vm.stats.vm.v_free_count", &a, &sz, NULL, 0);
|
|
|
|
ret.free = (double)a / allmem_pages;
|
|
|
|
ret.swap = getSwapFrac();
|
2020-11-17 12:14:24 -05:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2022-01-08 02:28:15 -05:00
|
|
|
printf("%u %lf %lf %lf %lf\n", allmem_pages,
|
|
|
|
ret.code, ret.cached, ret.free, ret.swap);
|
2017-02-18 16:06:47 -05:00
|
|
|
#endif
|
2022-01-08 02:28:15 -05:00
|
|
|
memcpy(call_data, &ret, sizeof(MemStripChartCallbackData));
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
#if __gnu_linux__
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
#include <X11/Intrinsic.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include "MemStripChart.h"
|
|
|
|
|
|
|
|
static unsigned int total_mem = 0;
|
|
|
|
|
|
|
|
int GetRamInKB(int type)
|
|
|
|
{
|
|
|
|
FILE *meminfo = fopen("/proc/meminfo", "r");
|
|
|
|
if(meminfo == NULL)
|
|
|
|
err(1, "fopen on /proc/meminfo failed: ");
|
|
|
|
|
|
|
|
char line[256];
|
|
|
|
int memory = -1;
|
|
|
|
int found = 0;
|
|
|
|
while(found == 0 && fgets(line, sizeof(line), meminfo))
|
|
|
|
{
|
|
|
|
if (type == 1) {
|
|
|
|
if((sscanf(line, "MemTotal: %d kB", &memory)) == 1)
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
if (type == 2) {
|
|
|
|
if(sscanf(line, "MemFree: %d kB", &memory) == 1)
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
if (type == 3) {
|
|
|
|
if(sscanf(line, "Buffers: %d kB", &memory) == 1)
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
if (type == 4) {
|
|
|
|
if(sscanf(line, "Cached: %d kB", &memory) == 1)
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
if (type == 5) {
|
|
|
|
if(sscanf(line, "SwapTotal: %d kB", &memory) == 1)
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
if (type == 6) {
|
|
|
|
if(sscanf(line, "SwapFree: %d kB", &memory) == 1)
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
warnx("failed to sscanf type %d", type);
|
|
|
|
fclose(meminfo);
|
|
|
|
return memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_total_mem(void)
|
|
|
|
{
|
|
|
|
if (total_mem <= 0)
|
|
|
|
total_mem = GetRamInKB(1);
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("MemTotal: %d\n", total_mem);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GetMemLoadPoint(Widget w, caddr_t closure, caddr_t call_data)
|
|
|
|
{
|
|
|
|
MemStripChartCallbackData ret;
|
|
|
|
|
|
|
|
init_total_mem();
|
|
|
|
/* free(1):
|
|
|
|
* total
|
|
|
|
* used = total - free - buffers - cache
|
|
|
|
|
|
|
|
* /proc/meminfo
|
|
|
|
* total = MemTotal
|
|
|
|
* code = total - free - buffers - cache (“used”)
|
|
|
|
* buffer = Buffers
|
|
|
|
* cached = Cached
|
|
|
|
* free = MemFree
|
|
|
|
*/
|
|
|
|
int mem_free = GetRamInKB(2);
|
|
|
|
int buffers = GetRamInKB(3);
|
|
|
|
int cached = GetRamInKB(4);
|
|
|
|
int swap_total = GetRamInKB(5);
|
|
|
|
int swap_free = GetRamInKB(6);
|
|
|
|
ret.code = (total_mem - mem_free - buffers - cached)/(float)total_mem;
|
|
|
|
ret.buffer = (buffers)/(float)total_mem;
|
|
|
|
ret.cached = (cached)/(float)total_mem;
|
|
|
|
ret.free = (mem_free)/(float)total_mem;
|
|
|
|
ret.swap = (swap_total - swap_free)/(float)swap_total;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("%u %lf %lf %lf %lf\n", total_mem,
|
|
|
|
ret.code, ret.cached, ret.free, ret.swap);
|
|
|
|
#endif
|
|
|
|
memcpy(call_data, &ret, sizeof(MemStripChartCallbackData));
|
2017-02-18 16:03:44 -05:00
|
|
|
}
|
|
|
|
|
2020-11-17 12:14:24 -05:00
|
|
|
#endif
|