Merge branch 'collectd-3.9'
[collectd.git] / src / cpufreq.c
1 /**
2  * collectd - src/cpufreq.c
3  * Copyright (C) 2005,2006  Peter Holik
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  * Authors:
20  *   Peter Holik <peter at holik.at>
21  **/
22
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
26
27 #define MODULE_NAME "cpufreq"
28
29 #if defined(KERNEL_LINUX)
30 # define CPUFREQ_HAVE_READ 1
31 #else
32 # define CPUFREQ_HAVE_READ 0
33 #endif
34
35 static char *cpufreq_file = "cpufreq-%s.rrd";
36
37 static char *ds_def[] =
38 {
39         "DS:value:GAUGE:"COLLECTD_HEARTBEAT":0:U",
40         NULL
41 };
42 static int ds_num = 1;
43
44 #ifdef KERNEL_LINUX
45 static int num_cpu = 0;
46 #endif
47
48 #define BUFSIZE 256
49
50 static void cpufreq_init (void)
51 {
52 #ifdef KERNEL_LINUX
53         int status;
54         char filename[BUFSIZE];
55
56         num_cpu = 0;
57
58         while (1)
59         {
60                 status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", num_cpu);
61                 if (status < 1 || status >= BUFSIZE)
62                         break;
63
64                 if (access(filename, R_OK))
65                         break;
66
67                 num_cpu++;
68         }
69
70         syslog (LOG_INFO, MODULE_NAME" found %d cpu(s)", num_cpu);
71 #endif /* defined(KERNEL_LINUX) */
72
73         return;
74 }
75
76 static void cpufreq_write (char *host, char *inst, char *val)
77 {
78         int status;
79         char file[BUFSIZE];
80
81         status = snprintf (file, BUFSIZE, cpufreq_file, inst);
82         if (status < 1 || status >= BUFSIZE)
83                 return;
84
85         rrd_update_file (host, file, val, ds_def, ds_num);
86 }
87
88 #if CPUFREQ_HAVE_READ
89 static void cpufreq_submit (int cpu_num, unsigned long long val)
90 {
91         char buf[BUFSIZE];
92         char cpu[16];
93
94         if (snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, val) >= BUFSIZE)
95                 return;
96         snprintf (cpu, 16, "%i", cpu_num);
97
98         plugin_submit (MODULE_NAME, cpu, buf);
99 }
100
101 static void cpufreq_read (void)
102 {
103 #ifdef KERNEL_LINUX
104         int status;
105         unsigned long long val;
106         int i = 0;
107         FILE *fp;
108         char filename[BUFSIZE];
109         char buffer[16];
110
111         for (i = 0; i < num_cpu; i++)
112         {
113                 status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
114                 if (status < 1 || status >= BUFSIZE)
115                         return;
116
117                 if ((fp = fopen (filename, "r")) == NULL)
118                 {
119                         syslog (LOG_WARNING, "cpufreq: fopen: %s", strerror (errno));
120                         return;
121                 }
122
123                 if (fgets (buffer, 16, fp) == NULL)
124                 {
125                         syslog (LOG_WARNING, "cpufreq: fgets: %s", strerror (errno));
126                         fclose (fp);
127                         return;
128                 }
129
130                 if (fclose (fp))
131                         syslog (LOG_WARNING, "cpufreq: fclose: %s", strerror (errno));
132
133                 /* You're seeing correctly: The file is reporting kHz values.. */
134                 val = atoll (buffer) * 1000;
135
136                 cpufreq_submit (i, val);
137         }
138 #endif /* defined(KERNEL_LINUX) */
139
140         return;
141 }
142 #else
143 #define cpufreq_read NULL
144 #endif
145 #undef BUFSIZE
146
147 void module_register (void)
148 {
149         plugin_register (MODULE_NAME, cpufreq_init, cpufreq_read, cpufreq_write);
150 }
151
152 #undef MODULE_NAME