wmclockmon: update change-log
[dockapps.git] / wmmemload / src / mem_linux.c
blob1c645c3bba5bdd07435021514152579769a9a0a1
1 /*
2 * mem_linux.c - module to get memory/swap usages, for GNU/Linxu
4 * Copyright(C) 2001,2002 Seiichi SATO <ssato@sh.rim.or.jp>
5 * Copyright(C) 2001 John McCutchan <ttb@tentacle.dhs.org>
7 * licensed under the GPL
8 */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <stdlib.h>
18 #if defined(HAVE_STRING_H)
19 #include <string.h>
20 #elif defined(HAVE_STRINGS_H)
21 #include <strings.h>
22 #endif
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <ctype.h>
28 #include <sys/utsname.h>
29 #include "mem.h"
31 static enum {
32 BEFORE_2_5_1,
33 BETWEEN_2_5_1_AND_3_14,
34 AFTER_3_14
35 } format;
37 #ifdef DEBUG
38 # define INLINE_STATIC static
39 #else
40 # define INLINE_STATIC static inline
41 #endif
43 /* initialize function */
44 void mem_init(void)
46 struct utsname un;
47 int version, patchlevel, sublevel;
49 /* get kernel version */
50 if (uname(&un) == -1)
51 perror("uname()");
52 sscanf(un.release, "%d.%d.%d", &version, &patchlevel, &sublevel);
54 /* new format ? (kernel >= 3.14 or 2.5.1pre?) */
55 /* see linux/fs/proc/proc_misc.c */
56 /* or linux/fs/proc/meminfo.c */
57 if ((version == 3 && patchlevel >= 14) || version > 3)
58 format = AFTER_3_14;
59 else if ((version == 2 && patchlevel >= 5 && sublevel >= 1) ||
60 (version == 2 && patchlevel >= 6 && sublevel >= 0) ||
61 version > 2)
62 format = BETWEEN_2_5_1_AND_3_14;
63 else
64 format = BEFORE_2_5_1;
68 INLINE_STATIC char *skip_line(const char *p)
70 while (*p != '\n')
71 p++;
72 return (char *) ++p;
75 INLINE_STATIC char *skip_token(const char *p)
77 while (isspace(*p))
78 p++;
79 while (*p && !isspace(*p))
80 p++;
81 return (char *)p;
84 INLINE_STATIC char *skip_multiple_token(const char *p, int count)
86 int i;
87 for (i = 0; i < count; i++)
88 p = skip_token(p);
89 return (char *)p;
92 /* return mem/swap usage in percent 0 to 100 */
93 void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
95 char buffer[BUFSIZ], *p;
96 int fd, len, i;
97 u_int64_t mtotal, mused, mfree, mbuffer, mcached, mavail;
98 u_int64_t stotal, sused, sfree, scached = 0;
100 /* read /proc/meminfo */
101 fd = open("/proc/meminfo", O_RDONLY);
102 if (fd < 0) {
103 perror("can't open /proc/meminfo");
104 exit(1);
106 len = read(fd, buffer, BUFSIZ - 1);
107 if (len < 0) {
108 perror("can't read /proc/meminfo");
109 exit(1);
111 close(fd);
113 buffer[len] = '\0';
114 p = buffer;
116 switch (format) {
117 case (BEFORE_2_5_1):
118 /* skip 3 lines */
119 for (i = 0; i < 3; i++)
120 p = skip_line(p);
121 p = skip_token(p);
122 /* examine each line of file */
123 mtotal = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
124 mfree = strtoul(p, &p, 0); p = skip_multiple_token(p, 5);
125 mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
126 mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
127 scached = strtoul(p, &p, 0);
128 break;
130 case (BETWEEN_2_5_1_AND_3_14):
131 p = skip_token(p);
132 /* examine each line of file */
133 mtotal = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
134 mfree = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
135 mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
136 mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
137 scached = strtoul(p, &p, 0);
138 break;
140 case (AFTER_3_14):
141 p = skip_token(p);
142 /* examine each line of file */
143 mtotal = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
144 mfree = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
145 mavail = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
146 mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
147 mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
148 scached = strtoul(p, &p, 0);
149 break;
153 /* skip N lines and examine info about swap */
154 /* kernel-2.4.2:N=8 2.4.16:N=7 */
155 while (isprint(p[0])) {
156 p = skip_line(p);
157 if (strncmp(p, "SwapTotal", 9) == 0)
158 break;
161 p = skip_token(p);
162 stotal = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
163 sfree = strtoul(p, &p, 0);
165 if (format == AFTER_3_14) {
166 *per_mem = 100 * (double) (mtotal - mavail) / (double) mtotal;
167 } else {
168 /* calculate memory usage in percent */
169 mused = mtotal - mfree;
170 if (opts->ignore_buffers)
171 mused -= mbuffer;
172 if (opts->ignore_cached)
173 mused -= mcached;
174 *per_mem = 100 * (double) mused / (double) mtotal;
177 /* calculate swap usage in percent */
178 sused = stotal - sfree;
179 if (opts->ignore_cached)
180 sused -= scached;
181 if (!stotal)
182 *per_swap = 0;
183 else
184 *per_swap = 100 * (double) sused / (double) stotal;
186 #if DEBUG
187 printf("-----------------------\n");
188 printf("MemTotal: %12ld\n", (unsigned long)mtotal);
189 printf("MemFree: %12ld\n", (unsigned long)mfree);
190 printf("Buffers: %12ld\n", (unsigned long)mbuffer);
191 printf("Cached: %12ld\n", (unsigned long)mcached);
192 printf("SwapTotal: %12ld\n", (unsigned long)stotal);
193 printf("SwapFree: %12ld\n", (unsigned long)sfree);
194 printf("SwapCached:%12ld\n", (unsigned long)scached);
195 printf("-----------------------\n\n");
196 #endif