diff --git a/wmmemload/src/Makefile.am b/wmmemload/src/Makefile.am index aad4d51..7dff778 100644 --- a/wmmemload/src/Makefile.am +++ b/wmmemload/src/Makefile.am @@ -14,7 +14,6 @@ wmmemload_SOURCES = \ EXTRA_wmmemload_SOURCES = \ mem_linux.c \ mem_freebsd.c \ - mem_freebsd_sysctl.c \ mem_openbsd.c \ mem_solaris.c diff --git a/wmmemload/src/mem_freebsd.c b/wmmemload/src/mem_freebsd.c index 00d10b1..3b12346 100644 --- a/wmmemload/src/mem_freebsd.c +++ b/wmmemload/src/mem_freebsd.c @@ -13,116 +13,132 @@ #include #include #include +#include #include "mem.h" #include #include -#include +#include +#include #include -static kvm_t *kvm_data = NULL; -static int pageshift; -static struct nlist nlst[] = { {"_cp_time"}, {"_cnt"}, {0} }; +static kvm_t *kvm_data; /* initialize function */ void mem_init(void) { - int pagesize = getpagesize(); - pageshift = 0; + kvm_data = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open"); - while (pagesize > 1) { - pageshift++; - pagesize >>= 1; - } + if (kvm_data == NULL) { + fprintf(stderr, "can't open kernel virtual memory"); + exit(1); + } - kvm_data = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open"); + /* drop setgid & setuid (the latter should not be there really) */ + seteuid(getuid()); + setegid(getgid()); - if (kvm_data == NULL) { - fprintf(stderr, "can't open kernel virtual memory"); - exit(1); - } - kvm_nlist(kvm_data, nlst); + if (geteuid() != getuid() || getegid() != getgid()) { + fprintf(stderr, "unable to drop privileges"); + exit(1); + } - if (nlst[0].n_type == 0 || nlst[1].n_type == 0) { - fprintf(stderr, "error extracting symbols"); - exit(1); - } - /* drop setgid & setuid (the latter should not be there really) */ - seteuid(getuid()); - setegid(getgid()); - - if (geteuid() != getuid() || getegid() != getgid()) { - fprintf(stderr, "unable to drop privileges"); - exit(1); - } + return; } +#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) + +static void getsysctl(const char *name, void *ptr, size_t len) +{ + size_t nlen = len; + + if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { + fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name, + strerror(errno)); + exit(1); + } + if (nlen != len) { + fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n", + name, (unsigned long)len, (unsigned long)nlen); + exit(1); + } +} /* return mem/swap usage in percent 0 to 100 */ void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts) { - struct vmmeter vm; - int bufspace; - static int swap_firsttime = 1; - static int swappgsin = -1; - static int swappgsout = -1; - static int swapmax = 0, swapused = 0; - time_t cur_time; - static time_t last_time_swap = 0; - u_int mused; - - /* get mem usage */ - if (kvm_read(kvm_data, nlst[0].n_value, &bufspace, sizeof(bufspace)) != - sizeof(bufspace)) - exit(1); - if (kvm_read(kvm_data, nlst[1].n_value, &vm, sizeof(vm)) != sizeof(vm)) - exit(1); - - /* get swap usage */ - /* only calculate when first time or when changes took place */ - /* do not call it more than 1 time per 2 seconds */ - /* otherwise it can eat up to 50% of CPU time on heavy swap activity */ - cur_time = time(NULL); - if (swap_firsttime || - (((vm.v_swappgsin > swappgsin) || (vm.v_swappgsout > swappgsout)) - && cur_time > last_time_swap + 1)) { - - struct kvm_swap swap; - int n; - - swapmax = 0; - swapused = 0; - - n = kvm_getswapinfo(kvm_data, &swap, 1, 0); - if (n >= 0 && swap.ksw_total != 0) { - swapmax = swap.ksw_total; - swapused = swap.ksw_used; - } - - swap_firsttime = 0; - last_time_swap = cur_time; - } - swappgsin = vm.v_swappgsin; - swappgsout = vm.v_swappgsout; - + u_int mtotal, mwired, mcached, mfree, mused; #ifdef DEBUG - printf ("-------------------\n"); - printf ("total:%10d\n", vm.v_page_count * vm.v_page_size); - printf ("free :%10d\n", vm.v_free_count * vm.v_page_size); - printf ("act :%10d\n", vm.v_active_count * vm.v_page_size); - printf ("inact:%10d\n", vm.v_inactive_count * vm.v_page_size); - printf ("wired:%10d\n", vm.v_wire_count * vm.v_page_size); - printf ("cache:%10d\n", vm.v_cache_count * vm.v_page_size); - printf ("-------------------\n"); + u_int pagesize; +#endif + u_int new_swappgsin, new_swappgsout; + static int swap_firsttime = 1; + static int swappgsin = -1; + static int swappgsout = -1; + static int swapmax, swapused; + time_t cur_time; + static time_t last_time_swap; + + + /* get mem usage */ + GETSYSCTL("vm.stats.vm.v_page_count", mtotal); + GETSYSCTL("vm.stats.vm.v_wire_count", mwired); + GETSYSCTL("vm.stats.vm.v_cache_count", mcached); + GETSYSCTL("vm.stats.vm.v_free_count", mfree); +#ifdef DEBUG + GETSYSCTL("hw.pagesize", pagesize); #endif - /* calc mem/swap usage in percent */ - mused = vm.v_page_count - vm.v_free_count; - if (opts->ignore_wired) mused -= vm.v_wire_count; - if (opts->ignore_cached) mused -= vm.v_cache_count; + /* get swap usage */ + /* only calculate when first time or when changes took place */ + /* do not call it more than 1 time per 2 seconds */ + /* otherwise it can eat up to 50% of CPU time on heavy swap activity */ + cur_time = time(NULL); - *per_mem = 100 * (double) mused / (double) vm.v_page_count; - *per_swap = 100 * (double) swapused / (double) swapmax; + GETSYSCTL("vm.stats.vm.v_swappgsin", new_swappgsin); + GETSYSCTL("vm.stats.vm.v_swappgsout", new_swappgsout); - if (*per_mem > 97) *per_mem = 100; + if (swap_firsttime || + (((new_swappgsin > swappgsin) || (new_swappgsout > swappgsout)) + && cur_time > last_time_swap + 1)) { + + struct kvm_swap swap; + int n; + + swapmax = 0; + swapused = 0; + + n = kvm_getswapinfo(kvm_data, &swap, 1, 0); + if (n >= 0 && swap.ksw_total != 0) { + swapmax = swap.ksw_total; + swapused = swap.ksw_used; + } + + swap_firsttime = 0; + last_time_swap = cur_time; + } + + swappgsin = new_swappgsin; + swappgsout = new_swappgsout; + +#ifdef DEBUG + printf("-------------------\n"); + printf("total:%10d\n", mtotal * pagesize); + printf("free :%10d\n", mfree * pagesize); + printf("wired:%10d\n", mwired * pagesize); + printf("cache:%10d\n", mcached * pagesize); + printf("-------------------\n"); +#endif + + /* calc mem/swap usage in percent */ + mused = mtotal - mfree; + if (opts->ignore_wired) + mused -= mwired; + if (opts->ignore_cached) + mused -= mcached; + *per_mem = 100 * (double) mused / (double) mtotal; + *per_swap = 100 * (double) swapused / (double) swapmax; + + if (*per_mem > 97) + *per_mem = 100; } diff --git a/wmmemload/src/mem_freebsd_sysctl.c b/wmmemload/src/mem_freebsd_sysctl.c deleted file mode 100644 index a872f46..0000000 --- a/wmmemload/src/mem_freebsd_sysctl.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * mem_freebsd.c - module to get memory/swap usages in percent, for FreeBSD - * - * Copyright (c) 2001, 2002 Seiichi SATO - * - * licensed under the GPL - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include "mem.h" - -#include -#include -#include -#include - -/* initialize function */ -void mem_init(void) -{ - return; -} - -/* return mem/swap usage in percent 0 to 100 */ -void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts) -{ - - struct vmtotal vm; - size_t size = sizeof(vm); - static int mib[] = { CTL_VM, VM_METER }; - - /* get mem usage */ - if (sysctl(mib, 2, &vm, &size, NULL, 0) < 0) - bzero(&vm, sizeof(vm)); - - /* calc mem usage in percent */ - /* FIXME: the total usage(t_rm and t_free) is incorrect?? */ - if (vm.t_rm > 0) - *per_mem = 100 * (double) vm.t_rm / (double) (vm.t_rm + vm.t_free); - if (*per_mem > 95) - *per_mem = 100; - -#ifdef DEBUG - printf("t_vm total virtual memory %6lu\n", vm.t_vm); - printf("t_rm total real memory in use %6lu\n", vm.t_rm); - printf("t_arm active real memory %6lu\n", vm.t_arm); - printf("t_rmshr shared real memory %6lu\n", vm.t_rmshr); - printf("t_armshr active shared real memory %6lu\n", vm.t_armshr); - printf("t_free free memory pages %6lu\n", vm.t_free); - printf("--------------------------------------------\n"); -#endif - - /* get swap usage */ - /* not written yet.. can i get swap usage via sysctl? */ - - *per_swap = 0; - return; -}