1 /*
2     KSysGuard, the KDE System Guard
3 
4     Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
5     Copyright (c) 1999-2000 Hans Petter Bieker <bieker@kde.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 
21 */
22 
23 #include <sys/param.h>
24 #include <sys/sysctl.h>
25 #include <sys/dkstat.h>
26 #include <sys/swap.h>
27 
28 #include <limits.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include "Command.h"
35 #include "memory.h"
36 #include "ksysguardd.h"
37 
38 static size_t Total = 0;
39 static size_t MFree = 0;
40 static size_t Used = 0;
41 static size_t Application = 0;
42 static size_t Active = 0;
43 static size_t InActive = 0;
44 static size_t STotal = 0;
45 static size_t SFree = 0;
46 static size_t SUsed = 0;
47 static int pageshift = 0;
48 
49 /* define pagetok in terms of pageshift */
50 #define pagetok(size) ((size) << pageshift)
51 
52 void swapmode(int *used, int *total);
53 
54 void
initMemory(struct SensorModul * sm)55 initMemory(struct SensorModul* sm)
56 {
57 	int pagesize;
58 	static int physmem_mib[] = { CTL_HW, HW_PHYSMEM };
59 	size_t size;
60 	/* get the page size with "getpagesize" and calculate pageshift from
61 	* it */
62 	pagesize = getpagesize();
63 	pageshift = 0;
64 	while (pagesize > 1) {
65 		pageshift++;
66 		pagesize >>= 1;
67 	}
68 	size = sizeof(Total);
69 	sysctl(physmem_mib, 2, &Total, &size, NULL, 0);
70 	Total /= 1024;
71 	swapmode(&SUsed, &STotal);
72 
73   registerMonitor("mem/physical/free", "integer", printMFree, printMFreeInfo, sm);
74 	registerMonitor("mem/physical/active", "integer", printActive, printActiveInfo, sm);
75 	registerMonitor("mem/physical/inactive", "integer", printInActive, printInActiveInfo, sm);
76 	registerMonitor("mem/physical/used", "integer", printUsed, printUsedInfo, sm);
77 	registerMonitor("mem/physical/application", "integer", printApplication, printApplicationInfo, sm);
78 	registerMonitor("mem/swap/free", "integer", printSwapFree, printSwapFreeInfo, sm);
79 	registerMonitor("mem/swap/used", "integer", printSwapUsed, printSwapUsedInfo, sm);
80 }
81 
82 void
exitMemory(void)83 exitMemory(void)
84 {
85 }
86 
87 int
updateMemory(void)88 updateMemory(void)
89 {
90 	static int vmtotal_mib[] = {CTL_VM, VM_METER};
91 	size_t size;
92 	struct vmtotal vmtotal;
93 	size = sizeof(vmtotal);
94 
95 	if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0)
96 		return -1;
97 
98 	MFree = pagetok(vmtotal.t_free);
99 	MFree /= 1024;
100 	Active = pagetok(vmtotal.t_arm);
101 	Active /= 1024;
102 	InActive = pagetok(vmtotal.t_rm);
103 	InActive /= 1024;
104 	InActive -= Active;
105 
106 	Used = Total - MFree;
107 	Application = Used;
108 
109 	swapmode(&SUsed, &STotal);
110 	SFree = STotal - SUsed;
111 	return 0;
112 }
113 
114 void
printMFree(const char * cmd)115 printMFree(const char* cmd)
116 {
117 	fprintf(CurrentClient, "%d\n", MFree);
118 }
119 
120 void
printMFreeInfo(const char * cmd)121 printMFreeInfo(const char* cmd)
122 {
123 	fprintf(CurrentClient, "Free Memory\t0\t%d\tKB\n", Total);
124 }
125 
126 void
printUsed(const char * cmd)127 printUsed(const char* cmd)
128 {
129 	fprintf(CurrentClient, "%d\n", Used);
130 }
131 
132 void
printUsedInfo(const char * cmd)133 printUsedInfo(const char* cmd)
134 {
135 	fprintf(CurrentClient, "Used Memory\t0\t%d\tKB\n", Total);
136 }
137 
138 void
printApplication(const char * cmd)139 printApplication(const char* cmd)
140 {
141 	fprintf(CurrentClient, "%d\n", Application);
142 }
143 
144 void
printApplicationInfo(const char * cmd)145 printApplicationInfo(const char* cmd)
146 {
147 	fprintf(CurrentClient, "Application Memory\t0\t%ld\tKB\n", Total);
148 }
149 
150 void
printActive(const char * cmd)151 printActive(const char* cmd)
152 {
153 	fprintf(CurrentClient, "%d\n", Active);
154 }
155 
156 void
printActiveInfo(const char * cmd)157 printActiveInfo(const char* cmd)
158 {
159 	fprintf(CurrentClient, "Active Memory\t0\t%d\tKB\n", Total);
160 }
161 
162 void
printInActive(const char * cmd)163 printInActive(const char* cmd)
164 {
165 	fprintf(CurrentClient, "%d\n", InActive);
166 }
167 
168 void
printInActiveInfo(const char * cmd)169 printInActiveInfo(const char* cmd)
170 {
171 	fprintf(CurrentClient, "InActive Memory\t0\t%d\tKB\n", Total);
172 }
173 
174 void
printSwapUsed(const char * cmd)175 printSwapUsed(const char* cmd)
176 {
177 	fprintf(CurrentClient, "%d\n", SUsed);
178 }
179 
180 void
printSwapUsedInfo(const char * cmd)181 printSwapUsedInfo(const char* cmd)
182 {
183 	fprintf(CurrentClient, "Used Swap Memory\t0\t%d\tKB\n", STotal);
184 }
185 
186 void
printSwapFree(const char * cmd)187 printSwapFree(const char* cmd)
188 {
189 	fprintf(CurrentClient, "%d\n", SFree);
190 }
191 
192 void
printSwapFreeInfo(const char * cmd)193 printSwapFreeInfo(const char* cmd)
194 {
195 	fprintf(CurrentClient, "Free Swap Memory\t0\t%d\tKB\n", STotal);
196 }
197 
198 /*
199 This function swapmode was originally written by Tobias
200 Weingartner <weingart@openbsd.org>
201 
202 Taken from OpenBSD top command
203 */
204 void
swapmode(int * used,int * total)205 swapmode (int *used, int *total)
206 {
207 	int     nswap, rnswap, i;
208 	struct swapent *swdev;
209 
210 	*total = *used = 0;
211 
212 	/* Number of swap devices */
213 	nswap = swapctl(SWAP_NSWAP, 0, 0);
214 	if (nswap == 0)
215 		return;
216 
217 	swdev = (struct swapent *) malloc(nswap * sizeof(*swdev));
218 	if (swdev == NULL)
219 	 	return;
220 
221 	rnswap = swapctl(SWAP_STATS, swdev, nswap);
222 	if (rnswap == -1) {
223     free(swdev);
224 		return;
225   }
226 
227 	/* if rnswap != nswap, then what? */
228 
229 	/* Total things up */
230 	for (i = 0; i < nswap; i++) {
231 		if (swdev[i].se_flags & SWF_ENABLE) {
232 			*used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
233 			*total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
234 		}
235 	}
236 
237 	free(swdev);
238 }
239