summaryrefslogtreecommitdiff
path: root/sysutils/ksysguardd/files/patch-FreeBSD__stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/ksysguardd/files/patch-FreeBSD__stat.c')
-rw-r--r--sysutils/ksysguardd/files/patch-FreeBSD__stat.c382
1 files changed, 382 insertions, 0 deletions
diff --git a/sysutils/ksysguardd/files/patch-FreeBSD__stat.c b/sysutils/ksysguardd/files/patch-FreeBSD__stat.c
new file mode 100644
index 000000000000..7f8d6dc63898
--- /dev/null
+++ b/sysutils/ksysguardd/files/patch-FreeBSD__stat.c
@@ -0,0 +1,382 @@
+--- FreeBSD/stat.c 1970-01-01 02:00:00.000000000 +0200
++++ FreeBSD/stat.c 2011-02-10 15:37:53.000000000 +0200
+@@ -0,0 +1,379 @@
++/*
++ KSysGuard, the KDE System Guard
++
++ Copyright (c) 2011 David Naylor <naylor.b.david@gmail.com>
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of version 2 of the GNU General Public
++ License as published by the Free Software Foundation.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++*/
++
++/*
++ * TODO
++ * - stray irq
++ * - cpu*:timer
++ */
++
++#include "stat.h"
++
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "Command.h"
++
++#define IRQ_NAME 32
++
++char *sysctl_dynread(const char *);
++
++static u_int context, context_last = 0;
++static u_int trap, trap_last = 0;
++static u_int syscall, syscall_last = 0;
++static u_int hardint, hardint_last = 0;
++static u_int softint, softint_last = 0;
++
++static u_int intrcnt, nintr = 0, msi_offset = 0;
++static char **intrname = NULL, *intrnamebuf;
++static long *intr = NULL, *intr_last, *intr_current;
++static int *intr_map = NULL;
++
++void initStat(struct SensorModul *sm) {
++ int irq, irq_len = 0, msi_len = 0;
++ size_t len = 0;
++ char name[IRQ_NAME], *cp;
++
++ sysctlbyname("hw.intrcnt", NULL, &len, NULL, 0);
++ intrcnt = len / sizeof(unsigned long);
++
++ if ((intr = malloc(intrcnt * 3 * sizeof (long))) == NULL) {
++ log_error("out of memory for intr");
++ return;
++ }
++ intr_last = &intr[intrcnt];
++ intr_current = &intr_last[intrcnt];
++
++ if ((intrname = malloc(intrcnt * sizeof(char *))) == NULL) {
++ log_error("out of memory for intrname");
++ return;
++ }
++
++ if ((intrnamebuf = sysctl_dynread("hw.intrnames")) == NULL) {
++ log_error("out of memory for intrnamebuf");
++ return;
++ }
++ for (cp = intrnamebuf, irq = 0; irq < intrcnt; ++irq) {
++ char *nextcp;
++ for (nextcp = cp; *nextcp != '\0'; ++nextcp);
++ if (strncmp(cp, "irq", 3) == 0) {
++ long irq2;
++ sscanf(cp + 3, "%ld", &irq2);
++ if (irq2 > 255)
++ ++msi_len;
++ else
++ if (irq_len < irq2)
++ irq_len = irq2;
++ } else if (nextcp == cp)
++ intrcnt = irq;
++ cp = nextcp + 1;
++ }
++ if (msi_len)
++ msi_offset = 255 - irq_len;
++ nintr = irq_len + msi_len + 1;
++ if ((intr_map = malloc(nintr * sizeof(int))) == NULL) {
++ log_error("out of memory for intr_map");
++ return;
++ }
++
++ for (irq = 0; irq < nintr; ++irq)
++ intr_map[irq] = -1;
++ for (cp = intrnamebuf, irq = 0; irq < intrcnt; ++irq) {
++ char *nextcp;
++ for (nextcp = cp; *nextcp != '\0'; ++nextcp)
++ if (*nextcp == ' ' && (*(nextcp + 1) == ' ' || *(nextcp + 1) == '\0'))
++ *nextcp = '\0';
++ intrname[irq] = cp;
++ if (strncmp(cp, "irq", 3) == 0) {
++ long irq2;
++ sscanf(cp + 3, "%ld", &irq2);
++ if (irq2 < 256)
++ intr_map[irq2] = irq;
++ else
++ intr_map[irq2 - msi_offset] = irq;
++ strncpy(cp, "IRQ", 3);
++ for(cp = cp + 4; *cp != ':'; ++cp);
++ for(; ; ++cp)
++ if (*cp == '\0')
++ break;
++ else if (*cp == ':')
++ if (*(cp + 1) == '\0')
++ *cp = '\0';
++ else
++ *cp = '(';
++ else if (*(cp + 1) == '\0')
++ *cp = ')';
++ else
++ *cp = *(cp + 1);
++ } else if (nextcp == cp)
++ intrcnt = irq;
++ cp = nextcp + 1;
++ }
++
++ registerMonitor("cpu/interrupts/hardint", "integer", printHardInt, printHardIntInfo, sm);
++ registerMonitor("cpu/interrupts/softint", "integer", printSoftInt, printSoftIntInfo, sm);
++ registerLegacyMonitor("cpu/interrupts/int00", "integer", printHardInt, printHardIntInfo, sm);
++
++ for (irq = 0; irq < nintr; ++irq) {
++ if (intr_map[irq] == -1)
++ continue;
++ if (irq > 255 - msi_offset)
++ snprintf(name, IRQ_NAME, "cpu/interrupts/int%03d", irq + msi_offset);
++ else
++ snprintf(name, IRQ_NAME, "cpu/interrupts/int%02d", irq + 1);
++ registerMonitor(name, "integer", printInterruptx, printInterruptxInfo, sm);
++ }
++
++ registerMonitor("cpu/context", "integer", printContext, printContextInfo, sm);
++ registerMonitor("cpu/trap", "integer", printTrap, printTrapInfo, sm);
++ registerMonitor("cpu/syscall", "integer", printSyscall, printSyscallInfo, sm);
++
++ updateStat();
++}
++
++void exitStat(void) {
++ int irq;
++ char name[IRQ_NAME];
++
++ if (intr != NULL) {
++ free(intr);
++ intr = NULL;
++ intr_current = NULL;
++ intr_last = NULL;
++ }
++
++ if (intrname != NULL) {
++ free(intrname);
++ intrname = NULL;
++ }
++
++ if (intrnamebuf != NULL) {
++ if (intr_map != NULL) {
++ removeMonitor("cpu/interrupts/hardint");
++ removeMonitor("cpu/interrupts/softint");
++ removeMonitor("cpu/interrupts/int00");
++
++ for (irq = 0; irq < nintr; ++irq) {
++ if (intr_map[irq] == -1)
++ continue;
++ if (irq > 255 - msi_offset)
++ snprintf(name, IRQ_NAME, "cpu/interrupts/int%03d", irq + msi_offset);
++ else
++ snprintf(name, IRQ_NAME, "cpu/interrupts/int%02d", irq + 1);
++ removeMonitor(name);
++ }
++
++ removeMonitor("cpu/context");
++ removeMonitor("cpu/trap");
++ removeMonitor("cpu/syscall");
++
++ free(intr_map);
++ intr_map = NULL;
++ }
++
++ free(intrnamebuf);
++ intrnamebuf = NULL;
++ }
++}
++
++int updateStat(void) {
++ int irq;
++ size_t len;
++ unsigned int current;
++ long *swap;
++
++#define GETSYSCTL(mib, var) \
++ len = sizeof(var); \
++ sysctlbyname(mib, &var, &len, NULL, 0);
++#define GETDIFFSYSCTL(mib, var) \
++ GETSYSCTL(mib, current); \
++ var = current - var##_last; \
++ var##_last = current;
++
++ GETDIFFSYSCTL("vm.stats.sys.v_swtch", context);
++ GETDIFFSYSCTL("vm.stats.sys.v_trap", trap);
++ GETDIFFSYSCTL("vm.stats.sys.v_syscall", syscall);
++ GETDIFFSYSCTL("vm.stats.sys.v_intr", hardint);
++ GETDIFFSYSCTL("vm.stats.sys.v_soft", softint);
++
++ len = sizeof(long) * intrcnt;
++ sysctlbyname("hw.intrcnt", intr_current, &len, NULL, 0);
++ for (irq = 0; irq < nintr; ++irq)
++ if (intr_map[irq] != -1)
++ intr[intr_map[irq]] = intr_current[intr_map[irq]] - intr_last[intr_map[irq]];
++ swap = intr_current;
++ intr_current = intr_last;
++ intr_last = swap;
++
++ return (0);
++
++#undef GETDIFFSYSCTL
++#undef GETSYSCTL
++}
++
++void printHardInt(const char *cmd) {
++ fprintf(CurrentClient, "%d\n", hardint);
++}
++
++void printHardIntInfo(const char *cmd) {
++ fprintf(CurrentClient, "Hardware Interrupts\t0\t0\t1/s\n");
++}
++
++void printSoftInt(const char *cmd) {
++ fprintf(CurrentClient, "%d\n", softint);
++}
++
++void printSoftIntInfo(const char *cmd) {
++ fprintf(CurrentClient, "Software Interrupts\t0\t0\t1/s\n");
++}
++
++void printInterruptx(const char *cmd) {
++ int irq;
++
++ sscanf(cmd + 18, "%d", &irq);
++ if (irq > 255 - msi_offset)
++ irq -= msi_offset - 1;
++ fprintf(CurrentClient, "%ld\n", intr[intr_map[irq - 1]]);
++}
++
++void printInterruptxInfo(const char *cmd) {
++ int irq;
++
++ sscanf(cmd + 18, "%d", &irq);
++ if (irq > 255 - msi_offset)
++ irq -= msi_offset - 1;
++ fprintf(CurrentClient, "%s\t0\t0\t1/s\n", intrname[intr_map[irq - 1]]);
++}
++
++void printContext(const char *cmd) {
++ fprintf(CurrentClient, "%u\n", context);
++}
++
++void printContextInfo(const char *cmd) {
++ fprintf(CurrentClient, "Context switches\t0\t0\t1/s\n");
++}
++
++void printTrap(const char *cmd) {
++ fprintf(CurrentClient, "%u\n", trap);
++}
++
++void printTrapInfo(const char *cmd) {
++ fprintf(CurrentClient, "Traps\t0\t0\t1/s\n");
++}
++
++void printSyscall(const char *cmd) {
++ fprintf(CurrentClient, "%u\n", syscall);
++}
++
++void printSyscallInfo(const char *cmd) {
++ fprintf(CurrentClient, "System Calls\t0\t0\t1/s\n");
++}
++
++/*
++ * Taken from http://cvsweb.freebsd.org/src/usr.bin/systat/fetch.c
++ */
++/*-
++ * Copyright (c) 1983, 1989, 1992, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++/*
++ * Read sysctl data with variable size. Try some times (with increasing
++ * buffers), fail if still too small.
++ * This is needed sysctls with possibly raplidly increasing data sizes,
++ * but imposes little overhead in the case of constant sizes.
++ * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds
++ * the requested data.
++ * If szp is not NULL, the size of the returned data will be written into *szp.
++ */
++
++/* Some defines: Number of tries. */
++#define SD_NTRIES 10
++/* Percent of over-allocation (initial) */
++#define SD_MARGIN 10
++/*
++ * Factor for over-allocation in percent (the margin is increased by this on
++ * any failed try).
++ */
++#define SD_FACTOR 50
++/* Maximum supported MIB depth */
++#define SD_MAXMIB 16
++char *
++sysctl_dynread(const char *n)
++{
++ char *rv = NULL;
++ int mib[SD_MAXMIB];
++ size_t mibsz = SD_MAXMIB;
++ size_t mrg = SD_MARGIN;
++ size_t sz;
++ int i;
++
++ /* cache the MIB */
++ if (sysctlnametomib(n, mib, &mibsz) == -1) {
++ return NULL;
++ }
++ for (i = 0; i < SD_NTRIES; i++) {
++ /* get needed buffer size */
++ if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1)
++ break;
++ sz += sz * mrg / 100;
++ if ((rv = (char *)malloc(sz)) == NULL)
++ return NULL;
++ if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) {
++ free(rv);
++ rv = NULL;
++ if (errno == ENOMEM) {
++ mrg += mrg * SD_FACTOR / 100;
++ } else
++ break;
++ } else {
++ /* success */
++ break;
++ }
++ }
++
++ return rv;
++}