1/* 2 * Unix SMB/CIFS implementation. 3 * Performance Counter Daemon 4 * 5 * Copyright (C) Marcin Krzysztof Porwit 2005 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include "perf.h" 23 24void init_cpudata_desc(PERF_DATA_BLOCK *data) 25{ 26 init_perf_counter(&(data->cpuInfo.cpuObjDesc), 27 &(data->cpuInfo.cpuObjDesc), 28 get_counter_id(data), 29 "Processor", 30 "The Processor object consists of counters that describe the behavior of the CPU.", 31 0, 32 PERF_OBJECT); 33 init_perf_counter(&(data->cpuInfo.userCPU), 34 &(data->cpuInfo.cpuObjDesc), 35 get_counter_id(data), 36 "\% User CPU Utilization", 37 "\% User CPU Utilization is the percentage of the CPU used by processes executing user code.", 38 PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT, 39 PERF_COUNTER); 40 init_perf_counter(&(data->cpuInfo.systemCPU), 41 &(data->cpuInfo.cpuObjDesc), 42 get_counter_id(data), 43 "\% System CPU Utilization", 44 "\% System CPU Utilization is the percentage of the CPU used by processes doing system calls.", 45 PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT, 46 PERF_COUNTER); 47 init_perf_counter(&(data->cpuInfo.niceCPU), 48 &(data->cpuInfo.cpuObjDesc), 49 get_counter_id(data), 50 "\% Nice CPU Utilization", 51 "\% Nice CPU Utilization is the percentage of the CPU used by processes running in nice mode.", 52 PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_NOSHOW, 53 PERF_COUNTER); 54 init_perf_counter(&(data->cpuInfo.idleCPU), 55 &(data->cpuInfo.cpuObjDesc), 56 get_counter_id(data), 57 "\% Idle CPU", 58 "\% Idle CPU is the percentage of the CPU not doing any work.", 59 PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_NOSHOW, 60 PERF_COUNTER); 61 62 return; 63} 64 65void get_cpuinfo(PERF_DATA_BLOCK *data) 66{ 67 int num, i; 68 unsigned int cpuid; 69 char buf[PROC_BUF]; 70 static FILE *fp = NULL; 71 72 if(!fp) 73 { 74 if(!(fp = fopen("/proc/stat", "r"))) 75 { 76 perror("get_cpuinfo: fopen"); 77 exit(1); 78 } 79 } 80 81 rewind(fp); 82 fflush(fp); 83 84 /* Read in the first line and discard it -- that has the CPU summary */ 85 if(!fgets(buf, sizeof(buf), fp)) 86 { 87 perror("get_cpuinfo: fgets"); 88 exit(1); 89 } 90 for(i = 0; i < data->cpuInfo.numCPUs; i++) 91 { 92 if(!fgets(buf, sizeof(buf), fp)) 93 { 94 perror("get_cpuinfo: fgets"); 95 exit(1); 96 } 97 num = sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu", 98 &cpuid, 99 &data->cpuInfo.data[i].user, 100 &data->cpuInfo.data[i].nice, 101 &data->cpuInfo.data[i].system, 102 &data->cpuInfo.data[i].idle); 103 if(i != cpuid) 104 { 105 perror("get_cpuinfo: /proc/stat inconsistent?"); 106 exit(1); 107 } 108 /* 109 Alternate way of doing things: 110 struct tms buffer; 111 data->PerfTime100nSec = times(&buffer); 112 */ 113 data->PerfTime100nSec += data->cpuInfo.data[i].user + 114 data->cpuInfo.data[i].nice + 115 data->cpuInfo.data[i].system + 116 data->cpuInfo.data[i].idle; 117 } 118 data->PerfTime100nSec /= data->cpuInfo.numCPUs; 119 return; 120} 121 122void init_cpu_data(PERF_DATA_BLOCK *data) 123{ 124 data->cpuInfo.data = calloc(data->cpuInfo.numCPUs, sizeof(*data->cpuInfo.data)); 125 if(!data->cpuInfo.data) 126 { 127 perror("init_cpu_data: out of memory"); 128 exit(1); 129 } 130 131 init_cpudata_desc(data); 132 133 get_cpuinfo(data); 134 135 return; 136} 137 138void output_cpu_desc(PERF_DATA_BLOCK *data, RuntimeSettings rt) 139{ 140 output_perf_desc(data->cpuInfo.cpuObjDesc, rt); 141 output_perf_desc(data->cpuInfo.userCPU, rt); 142 output_perf_desc(data->cpuInfo.niceCPU, rt); 143 output_perf_desc(data->cpuInfo.systemCPU, rt); 144 output_perf_desc(data->cpuInfo.idleCPU, rt); 145 if(data->cpuInfo.numCPUs > 1) 146 output_num_instances(data->cpuInfo.cpuObjDesc, data->cpuInfo.numCPUs + 1, rt); 147 148 return; 149} 150 151void output_cpuinfo(PERF_DATA_BLOCK *data, RuntimeSettings rt, int tdb_flags) 152{ 153 int i; 154 char buf[NAME_LEN]; 155 156 output_perf_counter(data->cpuInfo.userCPU, 157 data->cpuInfo.data[0].user, 158 rt, tdb_flags); 159 output_perf_counter(data->cpuInfo.systemCPU, 160 data->cpuInfo.data[0].system, 161 rt, tdb_flags); 162 output_perf_counter(data->cpuInfo.niceCPU, 163 data->cpuInfo.data[0].nice, 164 rt, tdb_flags); 165 output_perf_counter(data->cpuInfo.idleCPU, 166 data->cpuInfo.data[0].idle, 167 rt, tdb_flags); 168 if(data->cpuInfo.numCPUs > 1) 169 { 170 for(i = 0; i < data->cpuInfo.numCPUs; i++) 171 { 172 memset(buf, 0, NAME_LEN); 173 sprintf(buf, "cpu%d", i); 174 output_perf_instance(data->cpuInfo.cpuObjDesc.index, 175 i, 176 (void *)&(data->cpuInfo.data[i]), 177 sizeof(data->cpuInfo.data[i]), 178 buf, rt, tdb_flags); 179 } 180 181 memset(buf, 0, NAME_LEN); 182 sprintf(buf, "_Total"); 183 output_perf_instance(data->cpuInfo.cpuObjDesc.index, 184 i, 185 (void *)&(data->cpuInfo.data[i]), 186 sizeof(data->cpuInfo.data[i]), 187 buf, rt, tdb_flags); 188 } 189 return; 190} 191