#include #include #include #include #include #include #include #include #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; #ifdef VM_SWAPUSAGE /* 10.4+ */ struct xsw_usage xsu; #endif 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 xvm(int); void xnet(int); void (*statfn[])(int) = { xsample, xapm, xloadavg, xswap, xcpu, xvm, xnet, 0 }; static mach_port_t stat_port; void sampleinit(void) { 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; struct if_data *if_data; ifa_list = nil; sample.net_ifaces = 0; 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_obytes = 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->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; if_data = (struct if_data*)ifa->ifa_data; 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_obytes; sample.net_errors += if_data->ifi_ierrors + if_data->ifi_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 sampleevents(void) { 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; i