Based on patch by Pedro Gimeno Fortea for Debian bug #670151 [1].

[1] https://bugs.debian.org/670151
---
 wmmon/Makefile.am  |  2 +-
 wmmon/configure.ac |  1 +
 wmmon/ulllib.c     | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++
 wmmon/ulllib.h     | 50 ++++++++++++++++++++++++++++++++++++++
 wmmon/wmmon.c      | 71 ++++++++++++++++++++++++++++++------------------------
 5 files changed, 160 insertions(+), 32 deletions(-)
 create mode 100644 wmmon/ulllib.c
 create mode 100644 wmmon/ulllib.h

diff --git a/wmmon/Makefile.am b/wmmon/Makefile.am
index 2607302..52a3f9a 100644
--- a/wmmon/Makefile.am
+++ b/wmmon/Makefile.am
@@ -1,6 +1,6 @@
 bin_PROGRAMS = wmmon
 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
 
 AM_CFLAGS = $(x11_CFLAGS) $(dockapp_CFLAGS)
diff --git a/wmmon/configure.ac b/wmmon/configure.ac
index 045ac5a..57e6847 100644
--- a/wmmon/configure.ac
+++ b/wmmon/configure.ac
@@ -4,5 +4,6 @@ AC_CONFIG_SRCDIR([configure.ac])
 AC_PROG_CC
 PKG_CHECK_MODULES([x11], [x11])
 PKG_CHECK_MODULES([dockapp], [dockapp])
+AC_TYPE_LONG_LONG_INT
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
diff --git a/wmmon/ulllib.c b/wmmon/ulllib.c
new file mode 100644
index 0000000..52efc3c
--- /dev/null
+++ b/wmmon/ulllib.c
@@ -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;
+
diff --git a/wmmon/ulllib.h b/wmmon/ulllib.h
new file mode 100644
index 0000000..cade281
--- /dev/null
+++ b/wmmon/ulllib.h
@@ -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_ */
diff --git a/wmmon/wmmon.c b/wmmon/wmmon.c
index 385de13..b3b4210 100644
--- a/wmmon/wmmon.c
+++ b/wmmon/wmmon.c
@@ -28,6 +28,8 @@
        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), <k...@kix.es>)
                * Code style.
        13/3/2012 (Barry Kelly (wbk), <coy...@devio.us>)
@@ -108,6 +110,7 @@
 #include <libdockapp/wmgeneral.h>
 #include <libdockapp/misc.h>
 
+#include "ulllib.h"
 #include "wmmon-master.xpm"
 #include "wmmon-mask.xbm"
 
@@ -197,14 +200,14 @@ typedef struct {
        int his[HISTORY_ENTRIES];
        int hisaddcnt;
        long rt_stat;
-       long statlast;
+       ullong statlast;
        long rt_idle;
-       long idlelast;
+       ullong idlelast;
        /* Processors stats */
        long *cpu_stat;
-       long *cpu_last;
+       ullong *cpu_last;
        long *idle_stat;
-       long *idle_last;
+       ullong *idle_last;
 } stat_dev;
 
 stat_dev stat_device[MAX_STAT_DEVICES];
@@ -215,10 +218,10 @@ int nb_cpu, cpu_max;
 int getNbCPU(void);
 unsigned long getWidth(long, long);
 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 update_stat_cpu(stat_dev *, long *, long *);
+void update_stat_cpu(stat_dev *, ullong *, ullong *);
 void update_stat_io(stat_dev *);
 void update_stat_mem(stat_dev *st, stat_dev *st2);
 void update_stat_swp(stat_dev *);
@@ -240,7 +243,7 @@ void wmmon_routine(int argc, char **argv)
        int stat_online;
 
        long starttime, curtime, nexttime;
-       long istat, idle, *istat2, *idle2;
+       ullong istat, idle, *istat2, *idle2;
 
        FILE *fp;
        char *conffile = NULL;
@@ -307,9 +310,9 @@ void wmmon_routine(int argc, char **argv)
 
        nb_cpu = getNbCPU();
        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_last = calloc(nb_cpu, sizeof(long));
+       stat_device[0].idle_last = calloc(nb_cpu, sizeof(ullong));
        if (!stat_device[0].cpu_stat ||
            !stat_device[0].cpu_last ||
            !stat_device[0].idle_stat ||
@@ -318,8 +321,8 @@ void wmmon_routine(int argc, char **argv)
                exit(1);
        }
 
-       istat2 = calloc(nb_cpu, sizeof(long));
-       idle2 = calloc(nb_cpu, sizeof(long));
+       istat2 = calloc(nb_cpu, sizeof(ullong));
+       idle2 = calloc(nb_cpu, sizeof(ullong));
        if (!istat2 || !idle2) {
                fprintf(stderr, "%s: Unable to alloc memory !!\n", argv[0]);
                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);
 
-       st->rt_idle = idle - st->idlelast;
+       st->rt_idle = ullsub(&idle, &st->idlelast);
        st->idlelast = idle;
 
-       st->rt_stat = istat - st->statlast;
+       st->rt_stat = ullsub(&istat, &st->statlast);
        st->statlast = istat;
 
        if (nb_cpu > 1) {
@@ -587,10 +591,10 @@ void update_stat_cpu(stat_dev *st, long *istat2, long 
*idle2)
                unsigned long  max, j;
                cpu_max = 0; max = 0;
                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->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];
 
                        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)
 {
-       long j, k, istat, idle;
+       long j, k;
+       ullong istat, idle;
 
        /* Periodically re-sample. Sometimes we get anomalously high readings;
         * this discards them. */
@@ -625,10 +630,10 @@ void update_stat_io(stat_dev *st)
 
        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->rt_stat = istat - st->statlast;
+       st->rt_stat = ullsub(&istat, &st->statlast);
        st->statlast = istat;
 
        /* remember peak for scaling of upper-right meter. */
@@ -727,7 +732,7 @@ void update_stat_swp(stat_dev *st)
 
/*******************************************************************************\
 |* 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;
        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 *tokens = " \t\n";
        float f;
+       ullong ulltmp;
 
        *is = 0;
-       *ds = 0;
-       *idle = 0;
+       ullreset(ds);
+       ullreset(idle);
 
        if (!strncmp(devname, "cpu", 3)) {
                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 */
                                if (!strstr(line, "cpu ")) {
                                        sscanf(line, "cpu%d", &cpu);
-                                       ds2[cpu] = 0;
-                                       idle2[cpu] = 0;
+                                       ullreset(&ds2[cpu]);
+                                       ullreset(&idle2[cpu]);
                                }
                                p = strtok(line, tokens);
                                /* 1..3, 4 == idle, we don't want idle! */
                                for (i=0; i<3; i++) {
                                        p = strtok(NULL, tokens);
+                                       ullparse(&ulltmp, p);
                                        if (cpu == -1)
-                                               *ds += atol(p);
+                                               ulladd(ds, &ulltmp);
                                        else
-                                               ds2[cpu] += atol(p);
+                                               ulladd(&ds2[cpu], &ulltmp);
                                }
                                p = strtok(NULL, tokens);
                                if (cpu == -1)
-                                       *idle = atol(p);
+                                       ullparse(idle, p);
                                else
-                                       idle2[cpu] = atol(p);
+                                       ullparse(&idle2[cpu], p);
                        }
                }
                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++)
                                        p = strtok(NULL, tokens);
 
-                               *ds += atol(p);
+                               ullparse(&ulltmp, p);
+                               ulladd(ds, &ulltmp);
                                for (i = 7; i <= 10; i++)
                                        p = strtok(NULL, tokens);
 
-                               *ds += atol(p);
+                               ullparse(&ulltmp, p);
+                               ulladd(ds, &ulltmp);
                        }
                }
        }
-- 
2.11.0


-- 
To unsubscribe, send mail to wmaker-dev-unsubscr...@lists.windowmaker.org.

Reply via email to