global reindent, now with uncrustify hook enabled
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_meminfo.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2008--2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet 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      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23
24 /*
25  * File for parsing top-level /proc entities.
26  * Copyright Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com
27  * Copyright 1998-2003 Albert Cahalan
28  * June 2003, Fabian Frederick, disk and slab info
29  *
30  * This library is free software; you can redistribute it and/or
31  * modify it under the terms of the GNU Lesser General Public
32  * License as published by the Free Software Foundation; either
33  * version 2.1 of the License, or (at your option) any later version.
34  *
35  * This library is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
38  * Lesser General Public License for more details.
39  *
40  * You should have received a copy of the GNU Lesser General Public
41  * License along with this library; if not, write to the Free Software
42  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
43  */
44
45 #define BAD_OPEN_MESSAGE                                        \
46   "Error: /proc must be mounted\n"                                \
47   "  To mount /proc at boot you need an /etc/fstab line like:\n"  \
48   "      proc   /proc   proc    defaults\n"                       \
49   "  In the meantime, run \"mount proc /proc -t proc\"\n"
50
51 #define STAT_FILE    "/proc/stat"
52 // static int stat_fd = -1;
53 #define UPTIME_FILE  "/proc/uptime"
54 // static int uptime_fd = -1;
55 #define LOADAVG_FILE "/proc/loadavg"
56 // static int loadavg_fd = -1;
57 #define MEMINFO_FILE "/proc/meminfo"
58 static int meminfo_fd = -1;
59 #define VMINFO_FILE "/proc/vmstat"
60 // static int vminfo_fd = -1;
61
62 // As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit,
63 // and would need 1258 if the obsolete fields were there.
64 static char buf[2048];
65
66 /* This macro opens filename only if necessary and seeks to 0 so
67  * that successive calls to the functions are more efficient.
68  * It also reads the current contents of the file into the global buf.
69  */
70 #define FILE_TO_BUF(filename, fd) do {                           \
71     static int local_n;                                         \
72     if (fd == -1 && (fd = open (filename, O_RDONLY)) == -1) {    \
73       fputs (BAD_OPEN_MESSAGE, stderr);                        \
74       fflush (NULL);                                           \
75       _exit (102);                                             \
76     }                                                           \
77     lseek (fd, 0L, SEEK_SET);                                    \
78     if ((local_n = read (fd, buf, sizeof buf - 1)) < 0) {        \
79       perror (filename);                                       \
80       fflush (NULL);                                           \
81       _exit (103);                                             \
82     }                                                           \
83     buf[local_n] = '\0';                                        \
84 } while (0)
85
86
87 /***********************************************************************/
88 /*
89  * Copyright 1999 by Albert Cahalan; all rights reserved.
90  * This file may be used subject to the terms and conditions of the
91  * GNU Library General Public License Version 2, or any later version
92  * at your option, as published by the Free Software Foundation.
93  * This program is distributed in the hope that it will be useful,
94  * but WITHOUT ANY WARRANTY; without even the implied warranty of
95  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96  * GNU Library General Public License for more details.
97  */
98
99 typedef struct mem_table_struct
100 {
101   const char *name;     /* memory type name */
102   unsigned long *slot; /* slot in return struct */
103 } mem_table_struct;
104
105 static int compare_mem_table_structs (const void *a, const void *b)
106 {
107   return strcmp (((const mem_table_struct*) a)->name, ((const
108                                                         mem_table_struct*) b)->
109                  name);
110 }
111
112 /* example data, following junk, with comments added:
113  *
114  * MemTotal:        61768 kB    old
115  * MemFree:          1436 kB    old
116  * MemShared:           0 kB    old (now always zero; not calculated)
117  * Buffers:          1312 kB    old
118  * Cached:          20932 kB    old
119  * Active:          12464 kB    new
120  * Inact_dirty:      7772 kB    new
121  * Inact_clean:      2008 kB    new
122  * Inact_target:        0 kB    new
123  * Inact_laundry:       0 kB    new, and might be missing too
124  * HighTotal:           0 kB
125  * HighFree:            0 kB
126  * LowTotal:        61768 kB
127  * LowFree:          1436 kB
128  * SwapTotal:      122580 kB    old
129  * SwapFree:        60352 kB    old
130  * Inactive:        20420 kB    2.5.41+
131  * Dirty:               0 kB    2.5.41+
132  * Writeback:           0 kB    2.5.41+
133  * Mapped:           9792 kB    2.5.41+
134  * Slab:             4564 kB    2.5.41+
135  * Committed_AS:     8440 kB    2.5.41+
136  * PageTables:        304 kB    2.5.41+
137  * ReverseMaps:      5738       2.5.41+
138  * SwapCached:          0 kB    2.5.??+
139  * HugePages_Total:   220       2.5.??+
140  * HugePages_Free:    138       2.5.??+
141  * Hugepagesize:     4096 kB    2.5.??+
142  */
143
144 /* obsolete */
145 unsigned long kb_main_shared;
146 /* old but still kicking -- the important stuff */
147 unsigned long kb_main_buffers;
148 unsigned long kb_main_cached;
149 unsigned long kb_main_free;
150 unsigned long kb_main_total;
151 unsigned long kb_swap_free;
152 unsigned long kb_swap_total;
153 /* recently introduced */
154 unsigned long kb_high_free;
155 unsigned long kb_high_total;
156 unsigned long kb_low_free;
157 unsigned long kb_low_total;
158 /* 2.4.xx era */
159 unsigned long kb_active;
160 unsigned long kb_inact_laundry;
161 unsigned long kb_inact_dirty;
162 unsigned long kb_inact_clean;
163 unsigned long kb_inact_target;
164 unsigned long kb_swap_cached;  /* late 2.4 and 2.6+ only */
165 /* derived values */
166 unsigned long kb_swap_used;
167 unsigned long kb_main_used;
168 /* 2.5.41+ */
169 unsigned long kb_writeback;
170 unsigned long kb_slab;
171 unsigned long nr_reversemaps;
172 unsigned long kb_committed_as;
173 unsigned long kb_dirty;
174 unsigned long kb_inactive;
175 unsigned long kb_mapped;
176 unsigned long kb_pagetables;
177 // seen on a 2.6.x kernel:
178 static unsigned long kb_vmalloc_chunk;
179 static unsigned long kb_vmalloc_total;
180 static unsigned long kb_vmalloc_used;
181 // seen on 2.6.24-rc6-git12
182 static unsigned long kb_anon_pages;
183 static unsigned long kb_bounce;
184 static unsigned long kb_commit_limit;
185 static unsigned long kb_nfs_unstable;
186 static unsigned long kb_swap_reclaimable;
187 static unsigned long kb_swap_unreclaimable;
188
189 void meminfo (void)
190 {
191   char namebuf[16]; /* big enough to hold any row name */
192   mem_table_struct findme = { namebuf, NULL };
193   mem_table_struct *found;
194   char *head;
195   char *tail;
196   static const mem_table_struct mem_table[] = {
197     { "Active", &kb_active },         // important
198     { "AnonPages", &kb_anon_pages },
199     { "Bounce", &kb_bounce },
200     { "Buffers", &kb_main_buffers },  // important
201     { "Cached", &kb_main_cached },    // important
202     { "CommitLimit", &kb_commit_limit },
203     { "Committed_AS", &kb_committed_as },
204     { "Dirty", &kb_dirty },           // kB version of vmstat nr_dirty
205     { "HighFree", &kb_high_free },
206     { "HighTotal", &kb_high_total },
207     { "Inact_clean", &kb_inact_clean },
208     { "Inact_dirty", &kb_inact_dirty },
209     { "Inact_laundry", &kb_inact_laundry },
210     { "Inact_target", &kb_inact_target },
211     { "Inactive", &kb_inactive },     // important
212     { "LowFree", &kb_low_free },
213     { "LowTotal", &kb_low_total },
214     { "Mapped", &kb_mapped },         // kB version of vmstat nr_mapped
215     { "MemFree", &kb_main_free },     // important
216     { "MemShared", &kb_main_shared }, // important, but now gone!
217     { "MemTotal", &kb_main_total },   // important
218     { "NFS_Unstable", &kb_nfs_unstable },
219     { "PageTables", &kb_pagetables }, // kB version of vmstat nr_page_table_pages
220     { "ReverseMaps", &nr_reversemaps }, // same as vmstat nr_page_table_pages
221     { "SReclaimable", &kb_swap_reclaimable }, // "swap reclaimable" (dentry and inode structures)
222     { "SUnreclaim", &kb_swap_unreclaimable },
223     { "Slab", &kb_slab },             // kB version of vmstat nr_slab
224     { "SwapCached", &kb_swap_cached },
225     { "SwapFree", &kb_swap_free },    // important
226     { "SwapTotal", &kb_swap_total },  // important
227     { "VmallocChunk", &kb_vmalloc_chunk },
228     { "VmallocTotal", &kb_vmalloc_total },
229     { "VmallocUsed", &kb_vmalloc_used },
230     { "Writeback", &kb_writeback },   // kB version of vmstat nr_writeback
231   };
232   const int mem_table_count = sizeof(mem_table) / sizeof(mem_table_struct);
233
234   FILE_TO_BUF (MEMINFO_FILE, meminfo_fd);
235
236   kb_inactive = ~0UL;
237
238   head = buf;
239   for (;;)
240   {
241     tail = strchr (head, ':');
242     if (! tail)
243       break;
244     *tail = '\0';
245     if (strlen (head) >= sizeof(namebuf))
246     {
247       head = tail + 1;
248       goto nextline;
249     }
250     strcpy (namebuf, head);
251     found = bsearch (&findme, mem_table, mem_table_count,
252                      sizeof(mem_table_struct), compare_mem_table_structs
253                      );
254     head = tail + 1;
255     if (! found)
256       goto nextline;
257     *(found->slot) = (unsigned long) strtoull (head, &tail, 10);
258 nextline:
259     tail = strchr (head, '\n');
260     if (! tail)
261       break;
262     head = tail + 1;
263   }
264   if (! kb_low_total)   /* low==main except with large-memory support */
265   {
266     kb_low_total = kb_main_total;
267     kb_low_free = kb_main_free;
268   }
269   if (kb_inactive == ~0UL)
270   {
271     kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry;
272   }
273   kb_swap_used = kb_swap_total - kb_swap_free;
274   kb_main_used = kb_main_total - kb_main_free;
275 }