1 /*
2  * CPU usage plugin to fbpanel
3  *
4  * Copyright (C) 2004 by Alexandre Pereira da Silva <alexandre.pereira@poli.usp.br>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 /*
23  * A little bug fixed by Mykola <mykola@2ka.mipt.ru>:)
24  * FreeBSD support added by Andreas Wiese <aw@instandbesetzt.net>
25  */
26 
27 
28 #if defined __FreeBSD__ || defined __DragonFly__
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #include <sys/sysctl.h>
33 #include <stdio.h>
34 #endif
35 
36 #include "misc.h"
37 #include "../chart/chart.h"
38 
39 //#define DEBUGPRN
40 #include "dbg.h"
41 
42 /* cpu.c */
43 struct cpu_stat {
44     gulong u, n, s, i, w; // user, nice, system, idle, wait
45 };
46 
47 typedef struct {
48     chart_priv chart;
49     struct cpu_stat cpu_prev;
50     int timer;
51     gchar *colors[1];
52 } cpu_priv;
53 
54 
55 
56 static chart_class *k;
57 
58 static void cpu_destructor(plugin_instance *p);
59 
60 #if defined __linux__
61 static int
cpu_get_load(cpu_priv * c)62 cpu_get_load(cpu_priv *c)
63 {
64     gfloat a, b;
65     struct cpu_stat cpu, cpu_diff;
66     FILE *stat;
67     float total;
68     gchar buf[40];
69 
70     ENTER;
71     total = 0;
72     stat = fopen("/proc/stat", "r");
73     if(!stat)
74         goto end;
75     fscanf(stat, "cpu %lu %lu %lu %lu %lu", &cpu.u, &cpu.n, &cpu.s,
76         &cpu.i, &cpu.w);
77     fclose(stat);
78 
79     cpu_diff.u = cpu.u - c->cpu_prev.u;
80     cpu_diff.n = cpu.n - c->cpu_prev.n;
81     cpu_diff.s = cpu.s - c->cpu_prev.s;
82     cpu_diff.i = cpu.i - c->cpu_prev.i;
83     cpu_diff.w = cpu.w - c->cpu_prev.w;
84     c->cpu_prev = cpu;
85 
86     a = cpu_diff.u + cpu_diff.n + cpu_diff.s;
87     b = a + cpu_diff.i + cpu_diff.w;
88     total = b ?  a / b : 1.0;
89 
90 end:
91     DBG("total=%f a=%f b=%f\n", total, a, b);
92     g_snprintf(buf, sizeof(buf), "<b>Cpu:</b> %d%%", (int)(total * 100));
93     gtk_widget_set_tooltip_markup(((plugin_instance *)c)->pwid, buf);
94     k->add_tick(&c->chart, &total);
95     RET(TRUE);
96 
97 }
98 #elif defined __FreeBSD__ || defined __DragonFly__
99 static int
cpu_get_load(cpu_priv * c)100 cpu_get_load(cpu_priv * c)
101 {
102 	static int	mib[2] = {-1, -1}, init = 0;
103 	static size_t	j;
104 	long		ct[CPUSTATES];
105 
106 	gfloat		a      , b;
107 	struct cpu_stat	cpu;
108 	float		total;
109 	gchar		buf[40];
110 
111 	ENTER;
112 	total = 0;
113 
114 	if (init == 0) {
115 		j = 2;
116 		if (sysctlnametomib("kern.cp_time", mib, &j) == -1) {
117 			DBG("Couldn't get mib for kern.cp_time");
118 			RET(FALSE);
119 		}
120 		c->cpu_prev.u = 0;
121 		c->cpu_prev.n = 0;
122 		c->cpu_prev.s = 0;
123 		c->cpu_prev.i = 0;
124 		c->cpu_prev.w = 0;
125 		init = 1;
126 		j = sizeof(ct);
127 	}
128 	if (sysctl(mib, 2, ct, &j, NULL, 0) == -1) {
129 		DBG("Couldn't get cpu stats");
130 		RET(FALSE);
131 	}
132 
133 	a = ct[CP_USER] + ct[CP_NICE] + ct[CP_SYS] + ct[CP_INTR] -
134             (c->cpu_prev.u + c->cpu_prev.n + c->cpu_prev.s + c->cpu_prev.i);
135 	b = a + ct[CP_IDLE] - c->cpu_prev.w;
136 	total = b ? (float)a / b : 1.0;
137 
138 	c->cpu_prev.u = ct[CP_USER];
139 	c->cpu_prev.n = ct[CP_NICE];
140 	c->cpu_prev.s = ct[CP_SYS] ;
141 	c->cpu_prev.i = ct[CP_INTR];
142 	c->cpu_prev.w = ct[CP_IDLE];
143 
144 end:
145 	DBG("total=%f a=%f b=%f\n", total, a, b);
146 	g_snprintf(buf, sizeof(buf), "<b>Cpu:</b> %d%%", (int)(total * 100));
147 	gtk_widget_set_tooltip_markup(((plugin_instance *) c)->pwid, buf);
148 	k->add_tick(&c->chart, &total);
149 	RET(TRUE);
150 
151 }
152 #else
153 static int
cpu_get_load(cpu_priv * c)154 cpu_get_load(cpu_priv *c)
155 {
156     ENTER;
157     RET(0);
158 }
159 #endif
160 
161 static int
cpu_constructor(plugin_instance * p)162 cpu_constructor(plugin_instance *p)
163 {
164     cpu_priv *c;
165 
166     if (!(k = class_get("chart")))
167         RET(0);
168     if (!PLUGIN_CLASS(k)->constructor(p))
169         RET(0);
170     c = (cpu_priv *) p;
171     c->colors[0] = "green";
172     XCG(p->xc, "Color", &c->colors[0], str);
173 
174     k->set_rows(&c->chart, 1, c->colors);
175     gtk_widget_set_tooltip_markup(((plugin_instance *)c)->pwid, "<b>Cpu</b>");
176     cpu_get_load(c);
177     c->timer = g_timeout_add(2000, (GSourceFunc) cpu_get_load, (gpointer) c);
178     RET(1);
179 }
180 
181 
182 static void
cpu_destructor(plugin_instance * p)183 cpu_destructor(plugin_instance *p)
184 {
185     cpu_priv *c = (cpu_priv *) p;
186 
187     ENTER;
188     g_source_remove(c->timer);
189     PLUGIN_CLASS(k)->destructor(p);
190     class_put("chart");
191     RET();
192 }
193 
194 
195 
196 static plugin_class class = {
197     .count       = 0,
198     .type        = "cpu",
199     .name        = "Cpu usage",
200     .version     = "1.0",
201     .description = "Display cpu usage",
202     .priv_size   = sizeof(cpu_priv),
203     .constructor = cpu_constructor,
204     .destructor  = cpu_destructor,
205 };
206 
207 static plugin_class *class_ptr = (plugin_class *) &class;
208