int readCpuCounters(SFLHost_cpu_counters *cpu) { int gotData = NO; FILE *procFile; // We assume that the cpu counters struct has been initialized // with all zeros. procFile= fopen("/proc/loadavg", "r"); if(procFile) { // The docs are pretty clear about %f being "float" rather // that "double", so just give the pointers to fscanf. if(fscanf(procFile, "%f %f %f %"SCNu32"/%"SCNu32"", &cpu->load_one, &cpu->load_five, &cpu->load_fifteen, &cpu->proc_run, &cpu->proc_total) == 5) { gotData = YES; } if(cpu->proc_run > 0) { // subtract myself from the running process count, // otherwise it always shows at least 1. Thanks to // Dave Mangot for pointing this out. cpu->proc_run--; } fclose(procFile); } procFile = fopen("/proc/stat", "r"); if(procFile) { // ASCII numbers in /proc/stat may be 64-bit (if not now // then someday), so it seems safer to read into // 64-bit ints with scanf first, then copy them // into the host_cpu structure from there. This also // allows us to convert "jiffies" to milliseconds. uint64_t cpu_user=0; uint64_t cpu_nice =0; uint64_t cpu_system=0; uint64_t cpu_idle=0; uint64_t cpu_wio=0; uint64_t cpu_intr=0; uint64_t cpu_sintr=0; uint64_t cpu_interrupts=0; uint64_t cpu_contexts=0; #define JIFFY_TO_MS(i) (((i) * 1000L) / HZ) // limit the number of chars we will read from each line // (there can be more than this - fgets will chop for us) #define MAX_PROC_LINE_CHARS 240 char line[MAX_PROC_LINE_CHARS]; uint32_t lineNo = 0; while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) { if(++lineNo == 1) { if(sscanf(line, "cpu %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64"", &cpu_user, &cpu_nice, &cpu_system, &cpu_idle, &cpu_wio, &cpu_intr, &cpu_sintr) >= 4) { gotData = YES; cpu->cpu_user = (uint32_t)(JIFFY_TO_MS(cpu_user)); cpu->cpu_nice = (uint32_t)(JIFFY_TO_MS(cpu_nice)); cpu->cpu_system = (uint32_t)(JIFFY_TO_MS(cpu_system)); cpu->cpu_idle = (uint32_t)(JIFFY_TO_MS(cpu_idle)); cpu->cpu_wio = (uint32_t)(JIFFY_TO_MS(cpu_wio)); cpu->cpu_intr = (uint32_t)(JIFFY_TO_MS(cpu_intr)); cpu->cpu_sintr = (uint32_t)(JIFFY_TO_MS(cpu_sintr)); } } else { if(line[0] == 'c' && line[1] == 'p' && line[2] == 'u' && (line[3] >= '0' && line[3] <= '9')) { gotData = YES; cpu->cpu_num++; } else if(strncmp(line, "intr", 4) == 0) { // total interrupts is the second token on this line if(sscanf(line, "intr %"SCNu64"", &cpu_interrupts) == 1) { gotData = YES; cpu->interrupts = (uint32_t)cpu_interrupts; } } else if(strncmp(line, "ctxt", 4) == 0) { if(sscanf(line, "ctxt %"SCNu64"", &cpu_contexts) == 1) { gotData = YES; cpu->contexts = (uint32_t)cpu_contexts; } } } } fclose(procFile); } procFile = fopen("/proc/uptime", "r"); if(procFile) { float uptime = 0; if(fscanf(procFile, "%f", &uptime) == 1) { gotData = YES; cpu->uptime = (uint32_t)uptime; } fclose(procFile); } // GNU libc knows the number of processors so // use this as a cross-check (and take whichever is higher) u_int32_t cpus_avail = get_nprocs(); if(cpus_avail != cpu->cpu_num) { static int oneShotWarning = YES; if(oneShotWarning) { myLog(LOG_ERR, "WARNING: /proc/stat says %u cpus, but get_nprocs says %u\n", cpu->cpu_num, cpus_avail); oneShotWarning = NO; } if(cpus_avail > cpu->cpu_num) cpu->cpu_num = cpus_avail; } //cpu_speed. According to Ganglia/libmetrics we should // look first in /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq // but for now just take the first one from /proc/cpuinfo procFile = fopen("/proc/cpuinfo", "r"); if(procFile) { #undef MAX_PROC_LINE_CHARS #define MAX_PROC_LINE_CHARS 80 char line[MAX_PROC_LINE_CHARS]; while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) { if(strncmp(line, "cpu MHz", 7) == 0) { double cpu_mhz = 0.0; if(sscanf(line, "cpu MHz : %lf", &cpu_mhz) == 1) { gotData = YES; cpu->cpu_speed = (uint32_t)(cpu_mhz); break; } } } fclose(procFile); } return gotData; }
int readCpuCounters(SFLHost_cpu_counters *cpu) { mach_port_t machport = mach_host_self(); // share this at top level like xen handle $$$ int gotData = NO; struct clockinfo ci = { 0 }; size_t len = sizeof(ci); if(sysctlbyname("kern.clockrate", &ci, &len, NULL, 0) != 0) { myLog(LOG_ERR, "sysctl(<kern.clockrate>) failed : %s", strerror(errno)); } else { // cpu ticks. From ganglia/libmetrics/Darwin/metrics.c:cpu_user_func() mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; host_cpu_load_info_data_t cpuStats; kern_return_t ret = host_statistics(machport, HOST_CPU_LOAD_INFO, (host_info_t)&cpuStats, &count); if (ret != KERN_SUCCESS) { myLog(LOG_ERR, "readCpuCounters: host_statistics() : %s", strerror(errno)); } else { gotData = YES; cpu->cpu_user = (uint32_t)(JIFFY_TO_MS(cpuStats.cpu_ticks[CPU_STATE_USER], ci.hz)); cpu->cpu_nice = (uint32_t)(JIFFY_TO_MS(cpuStats.cpu_ticks[CPU_STATE_NICE], ci.hz)); cpu->cpu_system = (uint32_t)(JIFFY_TO_MS(cpuStats.cpu_ticks[CPU_STATE_SYSTEM], ci.hz)); cpu->cpu_idle = (uint32_t)(JIFFY_TO_MS(cpuStats.cpu_ticks[CPU_STATE_IDLE], ci.hz)); // $$$ // cpu->cpu_wio // cpu->cpu_intr // cpu->cpu_sintr } } double loadavg[3]; if(getloadavg(loadavg, 3) != -1) { gotData = YES; cpu->load_one = loadavg[0]; cpu->load_five = loadavg[1]; cpu->load_fifteen = loadavg[2]; } // $$$ // cpu->proc_run, // cpu->proc_total // $$$ // cpu->interrupts // cpu->contexts // cpu->uptime // num_cpus. From ganglia/libmetrics/Darwin/metrics.c:cpu_num_func() { int ncpu = 0; size_t len = sizeof(ncpu); if(sysctlbyname("hw.ncpu", &ncpu, &len, NULL, 0) != 0) { myLog(LOG_ERR, "sysctl(<ncpu>) failed : %s", strerror(errno)); } else { gotData = YES; cpu->cpu_num = (uint32_t)ncpu; } } //cpu_speed. From ganglia/libmetrics/Darwin/metrics.c:cpu_speed_func() { unsigned long cpu_speed = 0; size_t len = sizeof(cpu_speed); if(sysctlbyname("hw.cpufrequency", &cpu_speed, &len, NULL, 0) != 0) { myLog(LOG_ERR, "sysctl(<cpu_speed>) failed : %s", strerror(errno)); } else { gotData = YES; cpu->cpu_speed = (uint32_t)(cpu_speed / 1000000); // Hz to MHz } } return gotData; }