wmmon: Fix jiffy counter overflowing long on 32-bit systems.
Based on patch by Pedro Gimeno Fortea for Debian bug #670151 [1]. [1] https://bugs.debian.org/670151
This commit is contained in:
parent
cd2115dbe8
commit
3ec1a9cde3
|
@ -1,6 +1,6 @@
|
||||||
bin_PROGRAMS = wmmon
|
bin_PROGRAMS = wmmon
|
||||||
dist_man_MANS = wmmon.1
|
dist_man_MANS = wmmon.1
|
||||||
wmmon_SOURCES = wmmon.c wmmon-mask.xbm wmmon-master.xpm
|
wmmon_SOURCES = wmmon.c wmmon-mask.xbm wmmon-master.xpm ulllib.c ulllib.h
|
||||||
EXTRA_DIST = BUGS CHANGES HINTS
|
EXTRA_DIST = BUGS CHANGES HINTS
|
||||||
|
|
||||||
AM_CFLAGS = $(x11_CFLAGS) $(dockapp_CFLAGS)
|
AM_CFLAGS = $(x11_CFLAGS) $(dockapp_CFLAGS)
|
||||||
|
|
|
@ -4,5 +4,6 @@ AC_CONFIG_SRCDIR([configure.ac])
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
PKG_CHECK_MODULES([x11], [x11])
|
PKG_CHECK_MODULES([x11], [x11])
|
||||||
PKG_CHECK_MODULES([dockapp], [dockapp])
|
PKG_CHECK_MODULES([dockapp], [dockapp])
|
||||||
|
AC_TYPE_LONG_LONG_INT
|
||||||
AC_CONFIG_FILES([Makefile])
|
AC_CONFIG_FILES([Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
68
wmmon/ulllib.c
Normal file
68
wmmon/ulllib.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Unsigned long long arithmetic limited library, tailored for wmmon's
|
||||||
|
* specific needs.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Pedro Gimeno Fortea
|
||||||
|
*
|
||||||
|
* This file is part of wmmon.
|
||||||
|
*
|
||||||
|
* wmmon is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wmmon 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 wmmon; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_LONG_LONG_INT
|
||||||
|
|
||||||
|
#include "ulllib.h"
|
||||||
|
|
||||||
|
void ullreset(ullong *target) {
|
||||||
|
target->H = target->L = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ulladd(ullong *target, const ullong *toadd) {
|
||||||
|
unsigned long tmpL = toadd->L, tmpH = toadd->H;
|
||||||
|
target->L += tmpL;
|
||||||
|
|
||||||
|
/* Carry if the result is less than one of the operands */
|
||||||
|
target->H += tmpH + (target->L < tmpL);
|
||||||
|
}
|
||||||
|
|
||||||
|
long ullsub(const ullong *a, const ullong *b) {
|
||||||
|
/* Will wrap around correctly if necessary. Result is assumed to
|
||||||
|
fit a signed long. */
|
||||||
|
/* assert((a->H == b->H && a->L >= b->L)
|
||||||
|
|| (a->H == b->H + 1 && a->L < b->L)); */
|
||||||
|
return a->L - b->L;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ullparse(ullong *target, const char *str) {
|
||||||
|
ullong tmp;
|
||||||
|
|
||||||
|
ullreset(target);
|
||||||
|
while (*str >= '0' && *str <= '9') {
|
||||||
|
tmp = *target;
|
||||||
|
ulladd(target, target); /* *2 */
|
||||||
|
ulladd(target, target); /* *4 */
|
||||||
|
ulladd(target, &tmp); /* *5 */
|
||||||
|
ulladd(target, target); /* *10 */
|
||||||
|
tmp.H = 0;
|
||||||
|
tmp.L = *str - '0';
|
||||||
|
ulladd(target, &tmp); /* + digit */
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_LONG_LONG_INT */
|
||||||
|
|
||||||
|
typedef int make_iso_compilers_happy;
|
||||||
|
|
50
wmmon/ulllib.h
Normal file
50
wmmon/ulllib.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Unsigned long long arithmetic limited library, tailored for wmmon's
|
||||||
|
* specific needs.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Pedro Gimeno Fortea
|
||||||
|
*
|
||||||
|
* This file is part of wmmon.
|
||||||
|
*
|
||||||
|
* wmmon is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wmmon 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 wmmon; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ULLLIB_H_
|
||||||
|
#define __ULLLIB_H_
|
||||||
|
|
||||||
|
#ifdef HAVE_LONG_LONG_INT
|
||||||
|
|
||||||
|
typedef unsigned long long ullong;
|
||||||
|
|
||||||
|
#define ullreset(x) (*(x) = 0)
|
||||||
|
#define ulladd(x, y) (*(x) += *(y))
|
||||||
|
#define ullsub(x, y) ((long)(*(x) - *(y)))
|
||||||
|
#define ullparse(x, y) (*(x) = atoll(y))
|
||||||
|
|
||||||
|
#else /* ! HAVE_LONG_LONG_INT */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long H;
|
||||||
|
unsigned long L;
|
||||||
|
} ullong;
|
||||||
|
|
||||||
|
void ullreset(ullong *);
|
||||||
|
void ulladd(ullong *, const ullong *);
|
||||||
|
long ullsub(const ullong *, const ullong *);
|
||||||
|
void ullparse(ullong *, const char *);
|
||||||
|
|
||||||
|
#endif /* HAVE_LONG_LONG_INT */
|
||||||
|
|
||||||
|
#endif /* __ULLIB_H_ */
|
|
@ -28,6 +28,8 @@
|
||||||
Changes:
|
Changes:
|
||||||
----
|
----
|
||||||
|
|
||||||
|
17/03/2014 (Pedro Gimeno Fortea)
|
||||||
|
* Fix jiffy counter overflowing long on 32-bit systems.
|
||||||
17/06/2012 (Rodolfo García Peñas (kix), <kix@kix.es>)
|
17/06/2012 (Rodolfo García Peñas (kix), <kix@kix.es>)
|
||||||
* Code style.
|
* Code style.
|
||||||
13/3/2012 (Barry Kelly (wbk), <coydog@devio.us>)
|
13/3/2012 (Barry Kelly (wbk), <coydog@devio.us>)
|
||||||
|
@ -108,6 +110,7 @@
|
||||||
#include <libdockapp/wmgeneral.h>
|
#include <libdockapp/wmgeneral.h>
|
||||||
#include <libdockapp/misc.h>
|
#include <libdockapp/misc.h>
|
||||||
|
|
||||||
|
#include "ulllib.h"
|
||||||
#include "wmmon-master.xpm"
|
#include "wmmon-master.xpm"
|
||||||
#include "wmmon-mask.xbm"
|
#include "wmmon-mask.xbm"
|
||||||
|
|
||||||
|
@ -197,14 +200,14 @@ typedef struct {
|
||||||
int his[HISTORY_ENTRIES];
|
int his[HISTORY_ENTRIES];
|
||||||
int hisaddcnt;
|
int hisaddcnt;
|
||||||
long rt_stat;
|
long rt_stat;
|
||||||
long statlast;
|
ullong statlast;
|
||||||
long rt_idle;
|
long rt_idle;
|
||||||
long idlelast;
|
ullong idlelast;
|
||||||
/* Processors stats */
|
/* Processors stats */
|
||||||
long *cpu_stat;
|
long *cpu_stat;
|
||||||
long *cpu_last;
|
ullong *cpu_last;
|
||||||
long *idle_stat;
|
long *idle_stat;
|
||||||
long *idle_last;
|
ullong *idle_last;
|
||||||
} stat_dev;
|
} stat_dev;
|
||||||
|
|
||||||
stat_dev stat_device[MAX_STAT_DEVICES];
|
stat_dev stat_device[MAX_STAT_DEVICES];
|
||||||
|
@ -215,10 +218,10 @@ int nb_cpu, cpu_max;
|
||||||
int getNbCPU(void);
|
int getNbCPU(void);
|
||||||
unsigned long getWidth(long, long);
|
unsigned long getWidth(long, long);
|
||||||
int checksysdevs(void);
|
int checksysdevs(void);
|
||||||
void get_statistics(char *, long *, long *, long *, long *, long *);
|
void get_statistics(char *, long *, ullong *, ullong *, ullong *, ullong *);
|
||||||
void DrawActive(char *);
|
void DrawActive(char *);
|
||||||
|
|
||||||
void update_stat_cpu(stat_dev *, long *, long *);
|
void update_stat_cpu(stat_dev *, ullong *, ullong *);
|
||||||
void update_stat_io(stat_dev *);
|
void update_stat_io(stat_dev *);
|
||||||
void update_stat_mem(stat_dev *st, stat_dev *st2);
|
void update_stat_mem(stat_dev *st, stat_dev *st2);
|
||||||
void update_stat_swp(stat_dev *);
|
void update_stat_swp(stat_dev *);
|
||||||
|
@ -240,7 +243,7 @@ void wmmon_routine(int argc, char **argv)
|
||||||
int stat_online;
|
int stat_online;
|
||||||
|
|
||||||
long starttime, curtime, nexttime;
|
long starttime, curtime, nexttime;
|
||||||
long istat, idle, *istat2, *idle2;
|
ullong istat, idle, *istat2, *idle2;
|
||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *conffile = NULL;
|
char *conffile = NULL;
|
||||||
|
@ -307,9 +310,9 @@ void wmmon_routine(int argc, char **argv)
|
||||||
|
|
||||||
nb_cpu = getNbCPU();
|
nb_cpu = getNbCPU();
|
||||||
stat_device[0].cpu_stat = calloc(nb_cpu, sizeof(long));
|
stat_device[0].cpu_stat = calloc(nb_cpu, sizeof(long));
|
||||||
stat_device[0].cpu_last = calloc(nb_cpu, sizeof(long));
|
stat_device[0].cpu_last = calloc(nb_cpu, sizeof(ullong));
|
||||||
stat_device[0].idle_stat = calloc(nb_cpu, sizeof(long));
|
stat_device[0].idle_stat = calloc(nb_cpu, sizeof(long));
|
||||||
stat_device[0].idle_last = calloc(nb_cpu, sizeof(long));
|
stat_device[0].idle_last = calloc(nb_cpu, sizeof(ullong));
|
||||||
if (!stat_device[0].cpu_stat ||
|
if (!stat_device[0].cpu_stat ||
|
||||||
!stat_device[0].cpu_last ||
|
!stat_device[0].cpu_last ||
|
||||||
!stat_device[0].idle_stat ||
|
!stat_device[0].idle_stat ||
|
||||||
|
@ -318,8 +321,8 @@ void wmmon_routine(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
istat2 = calloc(nb_cpu, sizeof(long));
|
istat2 = calloc(nb_cpu, sizeof(ullong));
|
||||||
idle2 = calloc(nb_cpu, sizeof(long));
|
idle2 = calloc(nb_cpu, sizeof(ullong));
|
||||||
if (!istat2 || !idle2) {
|
if (!istat2 || !idle2) {
|
||||||
fprintf(stderr, "%s: Unable to alloc memory !!\n", argv[0]);
|
fprintf(stderr, "%s: Unable to alloc memory !!\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -570,16 +573,17 @@ void wmmon_routine(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void update_stat_cpu(stat_dev *st, long *istat2, long *idle2)
|
void update_stat_cpu(stat_dev *st, ullong *istat2, ullong *idle2)
|
||||||
{
|
{
|
||||||
long k, istat, idle;
|
long k;
|
||||||
|
ullong istat, idle;
|
||||||
|
|
||||||
get_statistics(st->name, &k, &istat, &idle, istat2, idle2);
|
get_statistics(st->name, &k, &istat, &idle, istat2, idle2);
|
||||||
|
|
||||||
st->rt_idle = idle - st->idlelast;
|
st->rt_idle = ullsub(&idle, &st->idlelast);
|
||||||
st->idlelast = idle;
|
st->idlelast = idle;
|
||||||
|
|
||||||
st->rt_stat = istat - st->statlast;
|
st->rt_stat = ullsub(&istat, &st->statlast);
|
||||||
st->statlast = istat;
|
st->statlast = istat;
|
||||||
|
|
||||||
if (nb_cpu > 1) {
|
if (nb_cpu > 1) {
|
||||||
|
@ -587,10 +591,10 @@ void update_stat_cpu(stat_dev *st, long *istat2, long *idle2)
|
||||||
unsigned long max, j;
|
unsigned long max, j;
|
||||||
cpu_max = 0; max = 0;
|
cpu_max = 0; max = 0;
|
||||||
for (cpu = 0; cpu < nb_cpu; cpu++) {
|
for (cpu = 0; cpu < nb_cpu; cpu++) {
|
||||||
st->idle_stat[cpu] = idle2[cpu] - st->idle_last[cpu];
|
st->idle_stat[cpu] = ullsub(&idle2[cpu], &st->idle_last[cpu]);
|
||||||
st->idle_last[cpu] = idle2[cpu];
|
st->idle_last[cpu] = idle2[cpu];
|
||||||
|
|
||||||
st->cpu_stat[cpu] = istat2[cpu] - st->cpu_last[cpu];
|
st->cpu_stat[cpu] = ullsub(&istat2[cpu], &st->cpu_last[cpu]);
|
||||||
st->cpu_last[cpu] = istat2[cpu];
|
st->cpu_last[cpu] = istat2[cpu];
|
||||||
|
|
||||||
j = st->cpu_stat[cpu] + st->idle_stat[cpu];
|
j = st->cpu_stat[cpu] + st->idle_stat[cpu];
|
||||||
|
@ -612,7 +616,8 @@ void update_stat_cpu(stat_dev *st, long *istat2, long *idle2)
|
||||||
|
|
||||||
void update_stat_io(stat_dev *st)
|
void update_stat_io(stat_dev *st)
|
||||||
{
|
{
|
||||||
long j, k, istat, idle;
|
long j, k;
|
||||||
|
ullong istat, idle;
|
||||||
|
|
||||||
/* Periodically re-sample. Sometimes we get anomalously high readings;
|
/* Periodically re-sample. Sometimes we get anomalously high readings;
|
||||||
* this discards them. */
|
* this discards them. */
|
||||||
|
@ -625,10 +630,10 @@ void update_stat_io(stat_dev *st)
|
||||||
|
|
||||||
get_statistics(st->name, &k, &istat, &idle, NULL, NULL);
|
get_statistics(st->name, &k, &istat, &idle, NULL, NULL);
|
||||||
|
|
||||||
st->rt_idle = idle - st->idlelast;
|
st->rt_idle = ullsub(&idle, &st->idlelast);
|
||||||
st->idlelast = idle;
|
st->idlelast = idle;
|
||||||
|
|
||||||
st->rt_stat = istat - st->statlast;
|
st->rt_stat = ullsub(&istat, &st->statlast);
|
||||||
st->statlast = istat;
|
st->statlast = istat;
|
||||||
|
|
||||||
/* remember peak for scaling of upper-right meter. */
|
/* remember peak for scaling of upper-right meter. */
|
||||||
|
@ -727,7 +732,7 @@ void update_stat_swp(stat_dev *st)
|
||||||
/*******************************************************************************\
|
/*******************************************************************************\
|
||||||
|* get_statistics *|
|
|* get_statistics *|
|
||||||
\*******************************************************************************/
|
\*******************************************************************************/
|
||||||
void get_statistics(char *devname, long *is, long *ds, long *idle, long *ds2, long *idle2)
|
void get_statistics(char *devname, long *is, ullong *ds, ullong *idle, ullong *ds2, ullong *idle2)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
static char *line = NULL;
|
static char *line = NULL;
|
||||||
|
@ -735,10 +740,11 @@ void get_statistics(char *devname, long *is, long *ds, long *idle, long *ds2, lo
|
||||||
char *p;
|
char *p;
|
||||||
char *tokens = " \t\n";
|
char *tokens = " \t\n";
|
||||||
float f;
|
float f;
|
||||||
|
ullong ulltmp;
|
||||||
|
|
||||||
*is = 0;
|
*is = 0;
|
||||||
*ds = 0;
|
ullreset(ds);
|
||||||
*idle = 0;
|
ullreset(idle);
|
||||||
|
|
||||||
if (!strncmp(devname, "cpu", 3)) {
|
if (!strncmp(devname, "cpu", 3)) {
|
||||||
fseek(fp_stat, 0, SEEK_SET);
|
fseek(fp_stat, 0, SEEK_SET);
|
||||||
|
@ -747,23 +753,24 @@ void get_statistics(char *devname, long *is, long *ds, long *idle, long *ds2, lo
|
||||||
int cpu = -1; /* by default, cumul stats => average */
|
int cpu = -1; /* by default, cumul stats => average */
|
||||||
if (!strstr(line, "cpu ")) {
|
if (!strstr(line, "cpu ")) {
|
||||||
sscanf(line, "cpu%d", &cpu);
|
sscanf(line, "cpu%d", &cpu);
|
||||||
ds2[cpu] = 0;
|
ullreset(&ds2[cpu]);
|
||||||
idle2[cpu] = 0;
|
ullreset(&idle2[cpu]);
|
||||||
}
|
}
|
||||||
p = strtok(line, tokens);
|
p = strtok(line, tokens);
|
||||||
/* 1..3, 4 == idle, we don't want idle! */
|
/* 1..3, 4 == idle, we don't want idle! */
|
||||||
for (i=0; i<3; i++) {
|
for (i=0; i<3; i++) {
|
||||||
p = strtok(NULL, tokens);
|
p = strtok(NULL, tokens);
|
||||||
|
ullparse(&ulltmp, p);
|
||||||
if (cpu == -1)
|
if (cpu == -1)
|
||||||
*ds += atol(p);
|
ulladd(ds, &ulltmp);
|
||||||
else
|
else
|
||||||
ds2[cpu] += atol(p);
|
ulladd(&ds2[cpu], &ulltmp);
|
||||||
}
|
}
|
||||||
p = strtok(NULL, tokens);
|
p = strtok(NULL, tokens);
|
||||||
if (cpu == -1)
|
if (cpu == -1)
|
||||||
*idle = atol(p);
|
ullparse(idle, p);
|
||||||
else
|
else
|
||||||
idle2[cpu] = atol(p);
|
ullparse(&idle2[cpu], p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((fp_loadavg = freopen("/proc/loadavg", "r", fp_loadavg)) == NULL)
|
if ((fp_loadavg = freopen("/proc/loadavg", "r", fp_loadavg)) == NULL)
|
||||||
|
@ -800,11 +807,13 @@ void get_statistics(char *devname, long *is, long *ds, long *idle, long *ds2, lo
|
||||||
for (i = 1; i <= 6; i++)
|
for (i = 1; i <= 6; i++)
|
||||||
p = strtok(NULL, tokens);
|
p = strtok(NULL, tokens);
|
||||||
|
|
||||||
*ds += atol(p);
|
ullparse(&ulltmp, p);
|
||||||
|
ulladd(ds, &ulltmp);
|
||||||
for (i = 7; i <= 10; i++)
|
for (i = 7; i <= 10; i++)
|
||||||
p = strtok(NULL, tokens);
|
p = strtok(NULL, tokens);
|
||||||
|
|
||||||
*ds += atol(p);
|
ullparse(&ulltmp, p);
|
||||||
|
ulladd(ds, &ulltmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue