From 8187859d2515ceb4bbbe6f608e24f490fb40094e Mon Sep 17 00:00:00 2001 From: rsc Date: Wed, 5 Oct 2005 13:30:49 +0000 Subject: new code from Jeff Sickel --- src/cmd/auxstats/Darwin.c | 442 +++++++++++++++++++++++++++++++--------------- 1 file changed, 301 insertions(+), 141 deletions(-) diff --git a/src/cmd/auxstats/Darwin.c b/src/cmd/auxstats/Darwin.c index 46ba5cbf..94a8794d 100644 --- a/src/cmd/auxstats/Darwin.c +++ b/src/cmd/auxstats/Darwin.c @@ -1,10 +1,4 @@ -/* - * No idea whether this will work. It does compile. - */ - #include -#include -#include #include #include #include @@ -15,119 +9,302 @@ #include #include #include +#include #include #include #include #include + +#include +#include +#include +#include +AUTOFRAMEWORK(CoreFoundation) +AUTOFRAMEWORK(IOKit) + #include "dat.h" +typedef struct Sample Sample; + +struct Sample +{ + uint seq; + host_cpu_load_info_data_t cpu, p_cpu; + vm_size_t pgsize; + double divisor; + uint64_t time, p_time; + vm_statistics_data_t vm_stat, p_vm_stat; + boolean_t purgeable_is_valid; + struct xsw_usage xsu; + boolean_t xsu_valid; + integer_t syscalls_mach, p_syscalls_mach; + integer_t syscalls_unix, p_syscalls_unix; + ulong csw, p_csw; + uint net_ifaces; + uvlong net_ipackets, p_net_ipackets; + uvlong net_opackets, p_net_opackets; + uvlong net_ibytes, p_net_ibytes; + uvlong net_obytes, p_net_obytes; + uvlong net_errors, p_net_errors; + ulong usecs; +}; + +static Sample sample; + +void xsample(int); +void xapm(int); void xloadavg(int); void xcpu(int); void xswap(int); -void xsysctl(int); +void xvm(int); void xnet(int); -void xkvm(int); void (*statfn[])(int) = { - xkvm, + xsample, + xapm, xloadavg, xswap, xcpu, - xsysctl, + xvm, xnet, 0 }; -static kvm_t *kvm; - -static struct nlist nl[] = { - { "_ifnet" }, - { "_cp_time" }, - { "" }, -}; +static mach_port_t stat_port; void -kvminit(void) +sampleinit(void) { - char buf[_POSIX2_LINE_MAX]; - - if(kvm) - return; - kvm = kvm_openfiles(nil, nil, nil, OREAD, buf); - if(kvm == nil) - return; - if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){ - kvm = nil; + mach_timebase_info_data_t info; + + if(stat_port) return; + + stat_port = mach_host_self(); + memset(&sample, 0, sizeof sample); + if(host_page_size(stat_port, &sample.pgsize) != KERN_SUCCESS) + sample.pgsize = 4096; + + // populate clock tick info for timestamps + mach_timebase_info(&info); + sample.divisor = 1000.0 * (double)info.denom/info.numer; + sample.time = mach_absolute_time(); +} + +void +samplenet(void) +{ + struct ifaddrs *ifa_list, *ifa; + + ifa_list = nil; + sample.net_ifaces = nil; + if(getifaddrs(&ifa_list) == 0){ + sample.p_net_ipackets = sample.net_ipackets; + sample.p_net_opackets = sample.net_opackets; + sample.p_net_ibytes = sample.net_ibytes; + sample.p_net_obtypes = sample.net_obytes; + sample.p_net_errors = sample.net_errors; + + sample.net_ipackets = 0; + sample.net_opackets = 0; + sample.net_ibytes = 0; + sample.net_obytes = 0; + sample.net_errors = 0; + sample.net_ifaces = 0; + + for(ifa=ifa_list; ifa; ifa=ifa->next){ + if(ifa->ifa_addr->sa_family != AF_LINK) + continue; + if((ifa->ifa_flags&(IFF_UP|IFF_RUNNING)) == 0) + continue; + if(ifa->ifa_data == nil) + continue; + if(strncmp(ifa->ifa_name, "lo", 2) == 0) /* loopback */ + continue; + + sample.net_ipackets += if_data->ifi_ipackets; + sample.net_opackets += if_data->ifi_opackets; + sample.net_ibytes += if_data->ifi_ibytes; + sample.net_obytes += if_data->ifi_obtypes; + sample.net_errors += if_data->ifi_ierrors + if_data->ifif_oerrors; + sample.net_ifaces++; + } + freeifaddrs(ifa_list); } } + +/* + * The following forces the program to be run with the suid root as + * all the other stat monitoring apps get set: + * + * -rwsr-xr-x 1 root wheel 83088 Mar 20 2005 /usr/bin/top + * -rwsrwxr-x 1 root admin 54048 Mar 20 2005 + * /Applications/Utilities/Activity Monitor.app/Contents/Resources/pmTool + * + * If Darwin eventually encompases more into sysctl then this + * won't be required. + */ void -xkvm(int first) +sampevents(void) { - if(first) - kvminit(); + uint i, j, pcnt, tcnt; + mach_msg_type_number_t count; + kern_return_t error; + processor_set_t *psets, pset; + task_t *tasks; + task_events_info_data_t events; + + if((error = host_processor_sets(stat_port, &psets, &pcnt)) != KERN_SUCCESS){ + Bprint(&bout, "host_processor_sets: %s (make sure auxstats is setuid root)\n", + mach_error_string(error)); + return; + } + + sample.p_syscalls_mach = sample.syscalls_mach; + sample.p_syscalls_unix = sample.syscalls_unix; + sample.p_csw = sample.csw; + + sample.syscalls_mach = 0; + sample.syscalls_unix = 0; + sample.csw = 0; + + for(i=0; istathz; - } - return; - } + ulong user, sys, idle, nice, t; - if((n=rsys("kern.cp_time", (char*)x, sizeof x)) < 5*sizeof(ulong)) + if(first) return; - Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz); - Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz); - Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz); - Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz); -#endif + sys = sample.cpu.cpu_ticks[CPU_STATE_SYSTEM] - + sample.p_cpu.cpu_ticks[CPU_STATE_SYSTEM]; + idle = sample.cpu.cpu_ticks[CPU_STATE_IDLE] - + sample.p_cpu.cpu_ticks[CPU_STATE_IDLE]; + user = sample.cpu.cpu_ticks[CPU_STATE_USER] - + sample.p_cpu.cpu_ticks[CPU_STATE_USER]; + nice = sample.cpu.cpu_ticks[CPU_STATE_NICE] - + sample.p_cpu.cpu_ticks[CPU_STATE_NICE]; + + t = sys+idle+user+nice; + + Bprint(&bout, "user =%lud %lud\n", user, t); + Bprint(&bout, "sys =%lud %lud\n", sys, t); + Bprint(&bout, "idle =%lud %lud\n", idle, t); + Bprint(&bout, "nice =%lud %lud\n", nice, t); } void @@ -222,32 +403,11 @@ xloadavg(int first) void xswap(int first) { -#if 0 - static struct kvm_swap s; - static ulong pgin, pgout; - int i, o; - static int pgsize; - - if(first){ - pgsize = getpagesize(); - if(pgsize == 0) - pgsize = 4096; - return; - } - - if(kvm == nil) + if(first) return; - - i = isys("vm.stats.vm.v_swappgsin"); - o = isys("vm.stats.vm.v_swappgsout"); - if(i != pgin || o != pgout){ - pgin = i; - pgout = o; - kvm_getswapinfo(kvm, &s, 1, 0); - } - - - Bprint(&bout, "swap %lld %lld\n", s.ksw_used*(vlong)pgsize, s.ksw_total*(vlong)pgsize); -#endif + + if(sample.xsu_valid) + Bprint(&bout, "swap %lld %lld\n", + (vlong)samle.xsu.xsu_used, + (vlong)sample.xsu.xsu_total); } - -- cgit v1.2.3