/**
* collectd - src/contextswitch.c
* Copyright (C) 2009 Patrik Weiskircher
+ * Copyright (C) 2010 Kimo Rosenbaum
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
*
* Authors:
* Patrik Weiskircher <weiskircher at inqnet.at>
+ * Kimo Rosenbaum <http://github.com/kimor79>
**/
#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#if !KERNEL_LINUX
+#ifdef HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+
+#if HAVE_SYSCTLBYNAME
+/* no global variables */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
+/* no global variables */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* #endif HAVE_PERFSTAT */
+
+#else
# error "No applicable input method."
#endif
-static void cs_submit (unsigned long context_switches)
+static void cs_submit (derive_t context_switches)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- values[0].derive = context_switches;
+ values[0].derive = (derive_t) context_switches;
vl.values = values;
vl.values_len = 1;
static int cs_read (void)
{
+#if HAVE_SYSCTLBYNAME
+ int value = 0;
+ size_t value_len = sizeof (value);
+ int status;
+
+ status = sysctlbyname ("vm.stats.sys.v_swtch",
+ &value, &value_len,
+ /* new pointer = */ NULL, /* new length = */ 0);
+ if (status != 0)
+ {
+ ERROR("contextswitch plugin: sysctlbyname "
+ "(vm.stats.sys.v_swtch) failed");
+ return (-1);
+ }
+
+ cs_submit (value);
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
FILE *fh;
char buffer[64];
int numfields;
- char *fields[2];
- unsigned long result = 0;
+ char *fields[3];
+ derive_t result = 0;
+ int status = -2;
fh = fopen ("/proc/stat", "r");
if (fh == NULL) {
return (-1);
}
- while (fgets(buffer, sizeof(buffer), fh))
+ while (fgets(buffer, sizeof(buffer), fh) != NULL)
{
- if (strncmp(buffer, "ctxt", 4))
+ char *endptr;
+
+ numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE (fields));
+ if (numfields != 2)
continue;
- numfields = strsplit(buffer, fields, 2);
- if (numfields != 2) {
- ERROR ("contextswitch plugin: ctxt in /proc/stat contains more than 2 fields.");
- break;
- }
+ if (strcmp("ctxt", fields[0]) != 0)
+ continue;
- result = strtoul(fields[1], NULL, 10);
- if (errno == ERANGE && result == ULONG_MAX) {
- ERROR ("contextswitch plugin: ctxt value in /proc/stat overflows.");
+ errno = 0;
+ endptr = NULL;
+ result = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+ if ((endptr == fields[1]) || (errno != 0)) {
+ ERROR ("contextswitch plugin: Cannot parse ctxt value: %s",
+ fields[1]);
+ status = -1;
break;
}
+ cs_submit(result);
+ status = 0;
break;
}
fclose(fh);
- if (result == 0) {
- ERROR ("contextswitch plugin: unable to find context switch value.");
- return -1;
+ if (status == -2)
+ ERROR ("contextswitch plugin: Unable to find context switch value.");
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+ int status = 0;
+ perfstat_cpu_total_t perfcputotal;
+
+ status = perfstat_cpu_total(NULL, &perfcputotal, sizeof(perfstat_cpu_total_t), 1);
+ if (status < 0)
+ {
+ char errbuf[1024];
+ ERROR ("contextswitch plugin: perfstat_cpu_total: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
}
- cs_submit(result);
+ cs_submit(perfcputotal.pswitch);
+ status = 0;
+#endif /* defined(HAVE_PERFSTAT) */
- return 0;
+ return status;
}
void module_register (void)