#include "memusage.h" #if defined(__FreeBSD__) || defined(__DragonFly__) # include # include # include #endif #if defined(__OpenBSD__) # include # include # include # include #endif #if defined(__FreeBSD__) || defined(__DragonFly__) static long int _sysctlfromname(const char *name, void *mib, int depth, size_t *len) { long int result; if (sysctlnametomib(name, mib, len) < 0) return -1; *len = sizeof(result); if (sysctl(mib, depth, &result, len, NULL, 0) < 0) return -1; return result; } #endif void _memsize_bytes_to_kb(unsigned long *bytes) { *bytes = (unsigned int)*bytes >> 10; } void _memusage_sysctl_getusage(unsigned long *mem_total, unsigned long *mem_used, unsigned long *mem_cached, unsigned long *mem_buffers, unsigned long *mem_shared, unsigned long *swp_total, unsigned long *swp_used) { size_t len; int i = 0; *mem_total = *mem_used = *mem_cached = *mem_buffers = *mem_shared = 0; *swp_total = *swp_used = 0; #if defined(__FreeBSD__) || defined(__DragonFly__) size_t miblen; int total_pages = 0, free_pages = 0, inactive_pages = 0; long int result = 0; int page_size = getpagesize(); int *mib = malloc(sizeof(int) * 4); if (mib == NULL) return; mib[0] = CTL_HW; mib[1] = HW_PHYSMEM; len = sizeof(*mem_total); if (sysctl(mib, 2, mem_total, &len, NULL, 0) == -1) return; *mem_total /= 1024; total_pages = _sysctlfromname("vm.stats.vm.v_page_count", mib, 4, &len); if (total_pages < 0) return; free_pages = _sysctlfromname("vm.stats.vm.v_free_count", mib, 4, &len); if (free_pages < 0) return; inactive_pages = _sysctlfromname("vm.stats.vm.v_inactive_count", mib, 4, &len); if (inactive_pages < 0) return; *mem_used = (total_pages - free_pages - inactive_pages) * page_size; _memsize_bytes_to_kb(mem_used); result = _sysctlfromname("vfs.bufspace", mib, 2, &len); if (result < 0) return; *mem_buffers = (result); _memsize_bytes_to_kb(mem_buffers); result = _sysctlfromname("vm.stats.vm.v_active_count", mib, 4, &len); if (result < 0) return; *mem_cached = (result * page_size); _memsize_bytes_to_kb(mem_cached); result = _sysctlfromname("vm.stats.vm.v_cache_count", mib, 4, &len); if (result < 0) return; *mem_shared = (result * page_size); _memsize_bytes_to_kb(mem_shared); result = _sysctlfromname("vm.swap_total", mib, 2, &len); if (result < 0) return; *swp_total = (result / 1024); miblen = 3; if (sysctlnametomib("vm.swap_info", mib, &miblen) == -1) return; struct xswdev xsw; // previous mib is important for this one... for (i = 0; ; i++) { mib[miblen] = i; len = sizeof(xsw); if (sysctl(mib, miblen + 1, &xsw, &len, NULL, 0) == -1) break; *swp_used += (unsigned long)xsw.xsw_used * page_size; } *swp_used >>= 10; E_FREE(mib); #elif defined(__OpenBSD__) static int mib[] = { CTL_HW, HW_PHYSMEM64 }; static int bcstats_mib[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT }; struct bcachestats bcstats; static int uvmexp_mib[] = { CTL_VM, VM_UVMEXP }; struct uvmexp uvmexp; int nswap, rnswap; struct swapent *swdev = NULL; len = sizeof(*mem_total); if (sysctl(mib, 2, mem_total, &len, NULL, 0) == -1) return; len = sizeof(uvmexp); if (sysctl(uvmexp_mib, 2, &uvmexp, &len, NULL, 0) == -1) return; len = sizeof(bcstats); if (sysctl(bcstats_mib, 3, &bcstats, &len, NULL, 0) == -1) return; // Don't fail if there's not swap! nswap = swapctl(SWAP_NSWAP, 0, 0); if (nswap == 0) goto swap_out; swdev = calloc(nswap, sizeof(*swdev)); if (swdev == NULL) goto swap_out; rnswap = swapctl(SWAP_STATS, swdev, nswap); if (rnswap == -1) goto swap_out; for (i = 0; i < nswap; i++) // nswap; i++) { if (swdev[i].se_flags & SWF_ENABLE) { *swp_used += (swdev[i].se_inuse / (1024 / DEV_BSIZE)); *swp_total += (swdev[i].se_nblks / (1024 / DEV_BSIZE)); } } swap_out: if (swdev) E_FREE(swdev); *mem_total /= 1024; *mem_cached = (uvmexp.pagesize * bcstats.numbufpages); _memsize_bytes_to_kb(mem_cached); *mem_used = (uvmexp.active * uvmexp.pagesize); _memsize_bytes_to_kb(mem_used); *mem_buffers = (uvmexp.pagesize * (uvmexp.npages - uvmexp.free)); _memsize_bytes_to_kb(mem_buffers); *mem_shared = (uvmexp.pagesize * uvmexp.wired); _memsize_bytes_to_kb(mem_shared); #endif }