eed69de0332927c88e9543f01cce4f16f78bfdf1
[kai/samba-autobuild/.git] / examples / perfcounter / perf_writer_cpu.c
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 3 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
24 void 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
65 void 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
122 void 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
138 void 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
151 void 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 }