]> git.ipfire.org Git - thirdparty/collectd.git/blame - src/memory.c
Merge pull request #4355 from atsampson/gcrypt-pkgconfig
[thirdparty/collectd.git] / src / memory.c
CommitLineData
7fa270a1
FF
1/**
2 * collectd - src/memory.c
8c16f03d 3 * Copyright (C) 2005-2014 Florian octo Forster
eeb8f7f4 4 * Copyright (C) 2009 Simon Kuhnle
f1b812b3 5 * Copyright (C) 2009 Manuel Sanmartin
7fa270a1
FF
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
293819d0 9 * Free Software Foundation; only version 2 of the License is applicable.
7fa270a1
FF
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * 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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Authors:
633c3966 21 * Florian octo Forster <octo at collectd.org>
eeb8f7f4 22 * Simon Kuhnle <simon at blarzwurst.de>
f1b812b3 23 * Manuel Sanmartin
7fa270a1
FF
24 **/
25
73681054 26#include "collectd.h"
a5377cf9 27
73681054 28#include "plugin.h"
6378ec28 29#include "utils/common/common.h"
7fa270a1 30
f22b9ecc
ZS
31#if (defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)) || \
32 defined(__OpenBSD__)
a937f260 33/* Implies BSD variant */
936c450a 34#include <sys/sysctl.h>
b8248eb1 35#endif
8fce2979 36#ifdef HAVE_SYS_VMMETER_H
936c450a 37#include <sys/vmmeter.h>
8fce2979 38#endif
7fa270a1 39
4d25c0e0 40#ifdef HAVE_MACH_KERN_RETURN_H
936c450a 41#include <mach/kern_return.h>
4d25c0e0
FF
42#endif
43#ifdef HAVE_MACH_MACH_INIT_H
936c450a 44#include <mach/mach_init.h>
4d25c0e0 45#endif
984e46be 46#ifdef HAVE_MACH_MACH_HOST_H
936c450a 47#include <mach/mach_host.h>
984e46be 48#endif
4d25c0e0 49#ifdef HAVE_MACH_HOST_PRIV_H
936c450a 50#include <mach/host_priv.h>
4d25c0e0 51#endif
f5adb596 52#ifdef HAVE_MACH_VM_STATISTICS_H
936c450a 53#include <mach/vm_statistics.h>
984e46be 54#endif
4d25c0e0 55
f05e9721 56#if HAVE_STATGRAB_H
936c450a 57#include <statgrab.h>
f05e9721
FF
58#endif
59
f1b812b3 60#if HAVE_PERFSTAT
936c450a
FF
61#include <libperfstat.h>
62#include <sys/protosw.h>
f1b812b3
MS
63#endif /* HAVE_PERFSTAT */
64
4d25c0e0 65/* vm_statistics_data_t */
e2df2097 66#if HAVE_HOST_STATISTICS
4d25c0e0
FF
67static mach_port_t port_host;
68static vm_size_t pagesize;
e2df2097 69/* #endif HAVE_HOST_STATISTICS */
4d25c0e0 70
74da5795 71#elif HAVE_SYSCTLBYNAME
5eebeafe
EF
72#if HAVE_SYSCTL && defined(KERNEL_NETBSD)
73static int pagesize;
74#include <unistd.h> /* getpagesize() */
75#else
b8248eb1 76/* no global variables */
5eebeafe 77#endif
74da5795 78/* #endif HAVE_SYSCTLBYNAME */
b8248eb1
FF
79
80#elif KERNEL_LINUX
4d25c0e0
FF
81/* no global variables */
82/* #endif KERNEL_LINUX */
83
b8248eb1 84#elif HAVE_LIBKSTAT
7fa270a1
FF
85static int pagesize;
86static kstat_t *ksp;
d13ba64e 87static kstat_t *ksz;
e4b274ed
FF
88/* #endif HAVE_LIBKSTAT */
89
003e2870
EF
90#elif HAVE_SYSCTL && __OpenBSD__
91/* OpenBSD variant does not have sysctlbyname */
92static int pagesize;
93/* #endif HAVE_SYSCTL && __OpenBSD__ */
94
f05e9721
FF
95#elif HAVE_LIBSTATGRAB
96/* no global variables */
97/* endif HAVE_LIBSTATGRAB */
f1b812b3
MS
98#elif HAVE_PERFSTAT
99static int pagesize;
f1b812b3 100/* endif HAVE_PERFSTAT */
e4b274ed 101#else
936c450a 102#error "No applicable input method."
e4b274ed 103#endif
7fa270a1 104
c920cda8 105#if KERNEL_NETBSD
30318d13 106#include <uvm/uvm_extern.h>
c920cda8
EF
107#endif
108
4e89060c 109static bool values_absolute = true;
f25d2076 110static bool values_percentage;
1aa8032d 111
936c450a 112static int memory_config(oconfig_item_t *ci) /* {{{ */
1aa8032d 113{
936c450a
FF
114 for (int i = 0; i < ci->children_num; i++) {
115 oconfig_item_t *child = ci->children + i;
116 if (strcasecmp("ValuesAbsolute", child->key) == 0)
117 cf_util_get_boolean(child, &values_absolute);
118 else if (strcasecmp("ValuesPercentage", child->key) == 0)
119 cf_util_get_boolean(child, &values_percentage);
120 else
121 ERROR("memory plugin: Invalid configuration option: "
122 "\"%s\".",
123 child->key);
124 }
125
307c875e 126 return 0;
1aa8032d
JK
127} /* }}} int memory_config */
128
936c450a 129static int memory_init(void) {
e2df2097 130#if HAVE_HOST_STATISTICS
936c450a
FF
131 port_host = mach_host_self();
132 host_page_size(port_host, &pagesize);
ec9234cd 133 /* #endif HAVE_HOST_STATISTICS */
4d25c0e0 134
74da5795 135#elif HAVE_SYSCTLBYNAME
5eebeafe
EF
136#if HAVE_SYSCTL && defined(KERNEL_NETBSD)
137 pagesize = getpagesize();
138#else
139/* no init stuff */
140#endif /* HAVE_SYSCTL && defined(KERNEL_NETBSD) */
30318d13 141 /* #endif HAVE_SYSCTLBYNAME */
b8248eb1 142
4d25c0e0 143#elif defined(KERNEL_LINUX)
30318d13
EF
144 /* no init stuff */
145 /* #endif KERNEL_LINUX */
4d25c0e0
FF
146
147#elif defined(HAVE_LIBKSTAT)
936c450a
FF
148 /* getpagesize(3C) tells me this does not fail.. */
149 pagesize = getpagesize();
150 if (get_kstat(&ksp, "unix", 0, "system_pages") != 0) {
151 ksp = NULL;
307c875e 152 return -1;
936c450a
FF
153 }
154 if (get_kstat(&ksz, "zfs", 0, "arcstats") != 0) {
155 ksz = NULL;
307c875e 156 return -1;
936c450a 157 }
d13ba64e 158
30318d13 159 /* #endif HAVE_LIBKSTAT */
38f27d54 160
4a2ec3e0 161#elif HAVE_SYSCTL && __OpenBSD__
f22b9ecc 162 /* OpenBSD variant does not have sysctlbyname */
936c450a
FF
163 pagesize = getpagesize();
164 if (pagesize <= 0) {
165 ERROR("memory plugin: Invalid pagesize: %i", pagesize);
307c875e 166 return -1;
936c450a 167 }
30318d13 168 /* #endif HAVE_SYSCTL && __OpenBSD__ */
38f27d54
FF
169
170#elif HAVE_LIBSTATGRAB
30318d13
EF
171 /* no init stuff */
172 /* #endif HAVE_LIBSTATGRAB */
7fa270a1 173
f1b812b3 174#elif HAVE_PERFSTAT
936c450a 175 pagesize = getpagesize();
f1b812b3 176#endif /* HAVE_PERFSTAT */
307c875e 177 return 0;
293819d0 178} /* int memory_init */
7fa270a1 179
936c450a
FF
180#define MEMORY_SUBMIT(...) \
181 do { \
182 if (values_absolute) \
6e41c3b1 183 plugin_dispatch_multivalue(vl, false, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \
936c450a 184 if (values_percentage) \
6e41c3b1 185 plugin_dispatch_multivalue(vl, true, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \
936c450a 186 } while (0)
577e34aa 187
ba047f90 188#if KERNEL_LINUX
189static void memory_submit_available(gauge_t value) {
190 value_list_t vl = VALUE_LIST_INIT;
191
192 vl.values = &(value_t){.gauge = value};
193 vl.values_len = 1;
194
195 sstrncpy(vl.plugin, "memory", sizeof(vl.plugin));
196 sstrncpy(vl.type, "memory", sizeof(vl.type));
197 sstrncpy(vl.type_instance, "available", sizeof(vl.type_instance));
198
199 plugin_dispatch_values(&vl);
200}
201#endif
202
936c450a 203static int memory_read_internal(value_list_t *vl) {
e2df2097 204#if HAVE_HOST_STATISTICS
936c450a
FF
205 kern_return_t status;
206 vm_statistics_data_t vm_data;
207 mach_msg_type_number_t vm_data_len;
208
209 gauge_t wired;
210 gauge_t active;
211 gauge_t inactive;
212 gauge_t free;
213
214 if (!port_host || !pagesize)
307c875e 215 return -1;
936c450a
FF
216
217 vm_data_len = sizeof(vm_data) / sizeof(natural_t);
218 if ((status = host_statistics(port_host, HOST_VM_INFO, (host_info_t)&vm_data,
219 &vm_data_len)) != KERN_SUCCESS) {
220 ERROR("memory-plugin: host_statistics failed and returned the value %i",
221 (int)status);
307c875e 222 return -1;
936c450a
FF
223 }
224
225 /*
226 * From <http://docs.info.apple.com/article.html?artnum=107918>:
227 *
228 * Wired memory
229 * This information can't be cached to disk, so it must stay in RAM.
230 * The amount depends on what applications you are using.
231 *
232 * Active memory
233 * This information is currently in RAM and actively being used.
234 *
235 * Inactive memory
236 * This information is no longer being used and has been cached to
237 * disk, but it will remain in RAM until another application needs
238 * the space. Leaving this information in RAM is to your advantage if
239 * you (or a client of your computer) come back to it later.
240 *
241 * Free memory
242 * This memory is not being used.
243 */
244
245 wired = (gauge_t)(((uint64_t)vm_data.wire_count) * ((uint64_t)pagesize));
246 active = (gauge_t)(((uint64_t)vm_data.active_count) * ((uint64_t)pagesize));
247 inactive =
248 (gauge_t)(((uint64_t)vm_data.inactive_count) * ((uint64_t)pagesize));
249 free = (gauge_t)(((uint64_t)vm_data.free_count) * ((uint64_t)pagesize));
250
251 MEMORY_SUBMIT("wired", wired, "active", active, "inactive", inactive, "free",
252 free);
ec9234cd 253 /* #endif HAVE_HOST_STATISTICS */
4d25c0e0 254
74da5795 255#elif HAVE_SYSCTLBYNAME
c920cda8
EF
256
257#if HAVE_SYSCTL && defined(KERNEL_NETBSD)
258 int mib[] = {CTL_VM, VM_UVMEXP2};
259 struct uvmexp_sysctl uvmexp;
260 gauge_t mem_active;
261 gauge_t mem_inactive;
262 gauge_t mem_free;
263 gauge_t mem_wired;
264 gauge_t mem_kernel;
265 size_t size;
266
30318d13
EF
267 memset(&uvmexp, 0, sizeof(uvmexp));
268 size = sizeof(uvmexp);
c920cda8 269
30318d13 270 if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
c920cda8 271 char errbuf[1024];
30318d13
EF
272 WARNING("memory plugin: sysctl failed: %s",
273 sstrerror(errno, errbuf, sizeof(errbuf)));
c920cda8
EF
274 return (-1);
275 }
276
30318d13
EF
277 assert(pagesize > 0);
278 mem_active = (gauge_t)(uvmexp.active * pagesize);
279 mem_inactive = (gauge_t)(uvmexp.inactive * pagesize);
280 mem_free = (gauge_t)(uvmexp.free * pagesize);
281 mem_wired = (gauge_t)(uvmexp.wired * pagesize);
282 mem_kernel = (gauge_t)((uvmexp.npages - (uvmexp.active + uvmexp.inactive +
283 uvmexp.free + uvmexp.wired)) *
284 pagesize);
285
286 MEMORY_SUBMIT("active", mem_active, "inactive", mem_inactive, "free",
287 mem_free, "wired", mem_wired, "kernel", mem_kernel);
288 /* #endif HAVE_SYSCTL && defined(KERNEL_NETBSD) */
c920cda8
EF
289
290#else /* Other HAVE_SYSCTLBYNAME providers */
936c450a
FF
291 /*
292 * vm.stats.vm.v_page_size: 4096
293 * vm.stats.vm.v_page_count: 246178
294 * vm.stats.vm.v_free_count: 28760
295 * vm.stats.vm.v_wire_count: 37526
296 * vm.stats.vm.v_active_count: 55239
297 * vm.stats.vm.v_inactive_count: 113730
298 * vm.stats.vm.v_cache_count: 10809
de33b26b
FC
299 * vm.stats.vm.v_user_wire_count: 0
300 * vm.stats.vm.v_laundry_count: 40394
936c450a 301 */
de33b26b
FC
302 const char *sysctl_keys[10] = {
303 "vm.stats.vm.v_page_size", "vm.stats.vm.v_page_count",
304 "vm.stats.vm.v_free_count", "vm.stats.vm.v_wire_count",
305 "vm.stats.vm.v_active_count", "vm.stats.vm.v_inactive_count",
306 "vm.stats.vm.v_cache_count", "vm.stats.vm.v_user_wire_count",
307 "vm.stats.vm.v_laundry_count", NULL};
308 double sysctl_vals[10];
936c450a
FF
309
310 for (int i = 0; sysctl_keys[i] != NULL; i++) {
311 int value;
312 size_t value_len = sizeof(value);
313
314 if (sysctlbyname(sysctl_keys[i], (void *)&value, &value_len, NULL, 0) ==
315 0) {
316 sysctl_vals[i] = value;
317 DEBUG("memory plugin: %26s: %g", sysctl_keys[i], sysctl_vals[i]);
318 } else {
319 sysctl_vals[i] = NAN;
320 }
321 } /* for (sysctl_keys) */
322
323 /* multiply all all page counts with the pagesize */
324 for (int i = 1; sysctl_keys[i] != NULL; i++)
325 if (!isnan(sysctl_vals[i]))
326 sysctl_vals[i] *= sysctl_vals[0];
327
328 MEMORY_SUBMIT("free", (gauge_t)sysctl_vals[2], "wired",
329 (gauge_t)sysctl_vals[3], "active", (gauge_t)sysctl_vals[4],
330 "inactive", (gauge_t)sysctl_vals[5], "cache",
de33b26b
FC
331 (gauge_t)sysctl_vals[6], "user_wire", (gauge_t)sysctl_vals[7],
332 "laundry", (gauge_t)sysctl_vals[8]);
c920cda8
EF
333
334#endif /* HAVE_SYSCTL && KERNEL_NETBSD */
ec9234cd 335 /* #endif HAVE_SYSCTLBYNAME */
b8248eb1 336
f05e9721 337#elif KERNEL_LINUX
936c450a
FF
338 FILE *fh;
339 char buffer[1024];
340
341 char *fields[8];
342 int numfields;
343
848b2394 344 bool mem_available_info = false;
6e41c3b1 345 bool detailed_slab_info = false;
936c450a
FF
346
347 gauge_t mem_total = 0;
348 gauge_t mem_used = 0;
349 gauge_t mem_buffered = 0;
350 gauge_t mem_cached = 0;
351 gauge_t mem_free = 0;
848b2394 352 gauge_t mem_available = 0;
936c450a
FF
353 gauge_t mem_slab_total = 0;
354 gauge_t mem_slab_reclaimable = 0;
355 gauge_t mem_slab_unreclaimable = 0;
356
357 if ((fh = fopen("/proc/meminfo", "r")) == NULL) {
0b7cd83a 358 WARNING("memory: fopen: %s", STRERRNO);
307c875e 359 return -1;
936c450a
FF
360 }
361
362 while (fgets(buffer, sizeof(buffer), fh) != NULL) {
363 gauge_t *val = NULL;
364
365 if (strncasecmp(buffer, "MemTotal:", 9) == 0)
366 val = &mem_total;
367 else if (strncasecmp(buffer, "MemFree:", 8) == 0)
368 val = &mem_free;
369 else if (strncasecmp(buffer, "Buffers:", 8) == 0)
370 val = &mem_buffered;
371 else if (strncasecmp(buffer, "Cached:", 7) == 0)
372 val = &mem_cached;
373 else if (strncasecmp(buffer, "Slab:", 5) == 0)
374 val = &mem_slab_total;
375 else if (strncasecmp(buffer, "SReclaimable:", 13) == 0) {
376 val = &mem_slab_reclaimable;
6e41c3b1 377 detailed_slab_info = true;
936c450a
FF
378 } else if (strncasecmp(buffer, "SUnreclaim:", 11) == 0) {
379 val = &mem_slab_unreclaimable;
6e41c3b1 380 detailed_slab_info = true;
848b2394
RA
381 } else if (strncasecmp(buffer, "MemAvailable:", 13) == 0) {
382 val = &mem_available;
383 mem_available_info = true;
936c450a
FF
384 } else
385 continue;
386
387 numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields));
388 if (numfields < 2)
389 continue;
390
391 *val = 1024.0 * atof(fields[1]);
392 }
393
394 if (fclose(fh)) {
0b7cd83a 395 WARNING("memory: fclose: %s", STRERRNO);
936c450a
FF
396 }
397
398 if (mem_total < (mem_free + mem_buffered + mem_cached + mem_slab_total))
307c875e 399 return -1;
936c450a 400
77e2fcd9
WZ
401 if (detailed_slab_info)
402 mem_used = mem_total -
403 (mem_free + mem_buffered + mem_cached + mem_slab_reclaimable);
404 else
405 mem_used =
406 mem_total - (mem_free + mem_buffered + mem_cached + mem_slab_total);
936c450a
FF
407
408 /* SReclaimable and SUnreclaim were introduced in kernel 2.6.19
409 * They sum up to the value of Slab, which is available on older & newer
410 * kernels. So SReclaimable/SUnreclaim are submitted if available, and Slab
411 * if not. */
ba047f90 412 if (detailed_slab_info)
936c450a
FF
413 MEMORY_SUBMIT("used", mem_used, "buffered", mem_buffered, "cached",
414 mem_cached, "free", mem_free, "slab_unrecl",
415 mem_slab_unreclaimable, "slab_recl", mem_slab_reclaimable);
416 else
417 MEMORY_SUBMIT("used", mem_used, "buffered", mem_buffered, "cached",
418 mem_cached, "free", mem_free, "slab", mem_slab_total);
ba047f90 419
420 if (mem_available_info)
421 memory_submit_available(mem_available);
ec9234cd 422 /* #endif KERNEL_LINUX */
7fa270a1 423
f05e9721 424#elif HAVE_LIBKSTAT
936c450a
FF
425 /* Most of the additions here were taken as-is from the k9toolkit from
426 * Brendan Gregg and are subject to change I guess */
427 long long mem_used;
428 long long mem_free;
429 long long mem_lock;
430 long long mem_kern;
431 long long mem_unus;
432 long long arcsize;
433
434 long long pp_kernel;
435 long long physmem;
436 long long availrmem;
437
438 if (ksp == NULL)
307c875e 439 return -1;
936c450a 440 if (ksz == NULL)
307c875e 441 return -1;
936c450a
FF
442
443 mem_used = get_kstat_value(ksp, "pagestotal");
444 mem_free = get_kstat_value(ksp, "pagesfree");
445 mem_lock = get_kstat_value(ksp, "pageslocked");
446 arcsize = get_kstat_value(ksz, "size");
447 pp_kernel = get_kstat_value(ksp, "pp_kernel");
448 physmem = get_kstat_value(ksp, "physmem");
449 availrmem = get_kstat_value(ksp, "availrmem");
450
451 mem_kern = 0;
452 mem_unus = 0;
453
454 if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL)) {
455 WARNING("memory plugin: one of used, free or locked is negative.");
307c875e 456 return -1;
936c450a
FF
457 }
458
459 mem_unus = physmem - mem_used;
460
461 if (mem_used < (mem_free + mem_lock)) {
462 /* source: http://wesunsolve.net/bugid/id/4909199
463 * this seems to happen when swap space is small, e.g. 2G on a 32G system
464 * we will make some assumptions here
465 * educated solaris internals help welcome here */
466 DEBUG("memory plugin: pages total is smaller than \"free\" "
467 "+ \"locked\". This is probably due to small "
468 "swap space");
469 mem_free = availrmem;
470 mem_used = 0;
471 } else {
472 mem_used -= mem_free + mem_lock;
473 }
474
475 /* mem_kern is accounted for in mem_lock */
476 if (pp_kernel < mem_lock) {
477 mem_kern = pp_kernel;
478 mem_lock -= pp_kernel;
479 } else {
480 mem_kern = mem_lock;
481 mem_lock = 0;
482 }
483
484 mem_used *= pagesize; /* If this overflows you have some serious */
485 mem_free *= pagesize; /* memory.. Why not call me up and give me */
486 mem_lock *= pagesize; /* some? ;) */
487 mem_kern *= pagesize; /* it's 2011 RAM is cheap */
488 mem_unus *= pagesize;
489 mem_kern -= arcsize;
490
491 MEMORY_SUBMIT("used", (gauge_t)mem_used, "free", (gauge_t)mem_free, "locked",
492 (gauge_t)mem_lock, "kernel", (gauge_t)mem_kern, "arc",
493 (gauge_t)arcsize, "unusable", (gauge_t)mem_unus);
ec9234cd 494 /* #endif HAVE_LIBKSTAT */
7fa270a1 495
4a2ec3e0 496#elif HAVE_SYSCTL && __OpenBSD__
f22b9ecc 497 /* OpenBSD variant does not have HAVE_SYSCTLBYNAME */
936c450a
FF
498 int mib[] = {CTL_VM, VM_METER};
499 struct vmtotal vmtotal = {0};
500 gauge_t mem_active;
501 gauge_t mem_inactive;
502 gauge_t mem_free;
503 size_t size;
504
505 size = sizeof(vmtotal);
506
507 if (sysctl(mib, 2, &vmtotal, &size, NULL, 0) < 0) {
0b7cd83a 508 WARNING("memory plugin: sysctl failed: %s", STRERRNO);
307c875e 509 return -1;
936c450a
FF
510 }
511
512 assert(pagesize > 0);
513 mem_active = (gauge_t)(vmtotal.t_arm * pagesize);
514 mem_inactive = (gauge_t)((vmtotal.t_rm - vmtotal.t_arm) * pagesize);
515 mem_free = (gauge_t)(vmtotal.t_free * pagesize);
516
517 MEMORY_SUBMIT("active", mem_active, "inactive", mem_inactive, "free",
518 mem_free);
4a2ec3e0 519 /* #endif HAVE_SYSCTL && __OpenBSD__ */
38f27d54 520
f05e9721 521#elif HAVE_LIBSTATGRAB
936c450a 522 sg_mem_stats *ios;
7fa270a1 523
936c450a
FF
524 ios = sg_get_mem_stats();
525 if (ios == NULL)
307c875e 526 return -1;
c791ba09 527
936c450a
FF
528 MEMORY_SUBMIT("used", (gauge_t)ios->used, "cached", (gauge_t)ios->cache,
529 "free", (gauge_t)ios->free);
ec9234cd 530 /* #endif HAVE_LIBSTATGRAB */
f1b812b3
MS
531
532#elif HAVE_PERFSTAT
936c450a
FF
533 perfstat_memory_total_t pmemory = {0};
534
535 if (perfstat_memory_total(NULL, &pmemory, sizeof(pmemory), 1) < 0) {
0b7cd83a 536 WARNING("memory plugin: perfstat_memory_total failed: %s", STRERRNO);
307c875e 537 return -1;
936c450a
FF
538 }
539
540 /* Unfortunately, the AIX documentation is not very clear on how these
541 * numbers relate to one another. The only thing is states explcitly
542 * is:
543 * real_total = real_process + real_free + numperm + real_system
544 *
545 * Another segmentation, which would be closer to the numbers reported
546 * by the "svmon" utility, would be:
547 * real_total = real_free + real_inuse
548 * real_inuse = "active" + real_pinned + numperm
549 */
550 MEMORY_SUBMIT("free", (gauge_t)(pmemory.real_free * pagesize), "cached",
551 (gauge_t)(pmemory.numperm * pagesize), "system",
552 (gauge_t)(pmemory.real_system * pagesize), "user",
553 (gauge_t)(pmemory.real_process * pagesize));
f1b812b3 554#endif /* HAVE_PERFSTAT */
293819d0 555
307c875e 556 return 0;
577e34aa
FF
557} /* }}} int memory_read_internal */
558
936c450a 559static int memory_read(void) /* {{{ */
577e34aa 560{
936c450a
FF
561 value_t v[1];
562 value_list_t vl = VALUE_LIST_INIT;
577e34aa 563
936c450a
FF
564 vl.values = v;
565 vl.values_len = STATIC_ARRAY_SIZE(v);
566 sstrncpy(vl.plugin, "memory", sizeof(vl.plugin));
567 sstrncpy(vl.type, "memory", sizeof(vl.type));
568 vl.time = cdtime();
577e34aa 569
307c875e 570 return memory_read_internal(&vl);
577e34aa 571} /* }}} int memory_read */
7fa270a1 572
936c450a
FF
573void module_register(void) {
574 plugin_register_complex_config("memory", memory_config);
575 plugin_register_init("memory", memory_init);
576 plugin_register_read("memory", memory_read);
2f0dfdda 577} /* void module_register */