emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 2fbd48f733 4/5: Fix process-attributes time precision on GNU/Linu


From: Paul Eggert
Subject: master 2fbd48f733 4/5: Fix process-attributes time precision on GNU/Linux
Date: Fri, 4 Mar 2022 22:29:25 -0500 (EST)

branch: master
commit 2fbd48f733426824cb89b958378a52cfb053774c
Author: Paul Eggert <eggert@cs.ucla.edu>
Commit: Paul Eggert <eggert@cs.ucla.edu>

    Fix process-attributes time precision on GNU/Linux
    
    * src/sysdep.c [GNU_LINUX]:
    (time_from_jiffies): Simplify by using time-convert.  Change args
    and result type.  All uses changed.
    (ltime_from_jiffies): Remove; call time_from_jiffies instead.
    (put_jiffies): New function.
    (get_up_time): Return Lisp_Object not struct timespec.
    All uses changed.  Simplify by using time-add.
    (system_process_attributes): Simplify by using the above.
    This fixes some minor problems where timestamps promised more
    precision than was actually available.  When info is not
    available (e.g., sysconf fails) do not place it into the alist.
    * src/timefns.c (float_time): Now extern.
---
 src/sysdep.c  | 124 ++++++++++++++++++++++------------------------------------
 src/systime.h |   1 +
 src/timefns.c |   2 +-
 3 files changed, 49 insertions(+), 78 deletions(-)

diff --git a/src/sysdep.c b/src/sysdep.c
index c9101f9481..a266307588 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -3177,70 +3177,45 @@ make_lisp_timeval (long sec, long usec)
 #endif
 
 #ifdef GNU_LINUX
-static struct timespec
-time_from_jiffies (unsigned long long tval, long hz)
-{
-  unsigned long long s = tval / hz;
-  unsigned long long frac = tval % hz;
-  int ns;
-
-  if (TYPE_MAXIMUM (time_t) < s)
-    time_overflow ();
-  if (LONG_MAX - 1 <= ULLONG_MAX / TIMESPEC_HZ
-      || frac <= ULLONG_MAX / TIMESPEC_HZ)
-    ns = frac * TIMESPEC_HZ / hz;
-  else
-    {
-      /* This is reachable only in the unlikely case that HZ * HZ
-        exceeds ULLONG_MAX.  It calculates an approximation that is
-        guaranteed to be in range.  */
-      long hz_per_ns = hz / TIMESPEC_HZ + (hz % TIMESPEC_HZ != 0);
-      ns = frac / hz_per_ns;
-    }
 
-  return make_timespec (s, ns);
+static Lisp_Object
+time_from_jiffies (unsigned long long ticks, Lisp_Object hz, Lisp_Object form)
+{
+  return Ftime_convert (Fcons (make_uint (ticks), hz), form);
 }
 
 static Lisp_Object
-ltime_from_jiffies (unsigned long long tval, long hz)
+put_jiffies (Lisp_Object attrs, Lisp_Object propname,
+            unsigned long long ticks, Lisp_Object hz)
 {
-  struct timespec t = time_from_jiffies (tval, hz);
-  return make_lisp_time (t);
+  return Fcons (Fcons (propname, time_from_jiffies (ticks, hz, Qnil)), attrs);
 }
 
-static struct timespec
+static Lisp_Object
 get_up_time (void)
 {
   FILE *fup;
-  struct timespec up = make_timespec (0, 0);
+  Lisp_Object up = Qnil;
 
   block_input ();
   fup = emacs_fopen ("/proc/uptime", "r");
 
   if (fup)
     {
-      unsigned long long upsec, upfrac;
+      unsigned long long upsec;
+      EMACS_UINT upfrac;
       int upfrac_start, upfrac_end;
 
-      if (fscanf (fup, "%llu.%n%llu%n",
+      if (fscanf (fup, "%llu.%n%"pI"u%n",
                  &upsec, &upfrac_start, &upfrac, &upfrac_end)
          == 2)
        {
-         if (TYPE_MAXIMUM (time_t) < upsec)
-           {
-             upsec = TYPE_MAXIMUM (time_t);
-             upfrac = TIMESPEC_HZ - 1;
-           }
-         else
-           {
-             int upfraclen = upfrac_end - upfrac_start;
-             for (; upfraclen < LOG10_TIMESPEC_HZ; upfraclen++)
-               upfrac *= 10;
-             for (; LOG10_TIMESPEC_HZ < upfraclen; upfraclen--)
-               upfrac /= 10;
-             upfrac = min (upfrac, TIMESPEC_HZ - 1);
-           }
-         up = make_timespec (upsec, upfrac);
+         EMACS_INT hz = 1;
+         for (int i = upfrac_start; i < upfrac_end; i++)
+           hz *= 10;
+         Lisp_Object sec = make_uint (upsec);
+         Lisp_Object subsec = Fcons (make_fixnum (upfrac), make_fixnum (hz));
+         up = Ftime_add (sec, subsec);
        }
       fclose (fup);
     }
@@ -3361,7 +3336,6 @@ system_process_attributes (Lisp_Object pid)
   unsigned long long u_time, s_time, cutime, cstime, start;
   long priority, niceness, rss;
   unsigned long minflt, majflt, cminflt, cmajflt, vsize;
-  struct timespec tnow, tstart, tboot, telapsed, us_time;
   double pcpu, pmem;
   Lisp_Object attrs = Qnil;
   Lisp_Object decoded_cmd;
@@ -3449,45 +3423,41 @@ system_process_attributes (Lisp_Object pid)
          attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (majflt)), attrs);
          attrs = Fcons (Fcons (Qcminflt, INT_TO_INTEGER (cminflt)), attrs);
          attrs = Fcons (Fcons (Qcmajflt, INT_TO_INTEGER (cmajflt)), attrs);
+
          clocks_per_sec = sysconf (_SC_CLK_TCK);
-         if (clocks_per_sec < 0)
-           clocks_per_sec = 100;
-         attrs = Fcons (Fcons (Qutime,
-                               ltime_from_jiffies (u_time, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qstime,
-                               ltime_from_jiffies (s_time, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qtime,
-                               ltime_from_jiffies (s_time + u_time,
-                                                   clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qcutime,
-                               ltime_from_jiffies (cutime, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qcstime,
-                               ltime_from_jiffies (cstime, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qctime,
-                               ltime_from_jiffies (cstime + cutime,
-                                                   clocks_per_sec)),
-                        attrs);
+         if (0 < clocks_per_sec)
+           {
+             Lisp_Object hz = make_int (clocks_per_sec);
+             attrs = put_jiffies (attrs, Qutime, u_time, hz);
+             attrs = put_jiffies (attrs, Qstime, s_time, hz);
+             attrs = put_jiffies (attrs, Qtime, s_time + u_time, hz);
+             attrs = put_jiffies (attrs, Qcutime, cutime, hz);
+             attrs = put_jiffies (attrs, Qcstime, cstime, hz);
+             attrs = put_jiffies (attrs, Qctime, cstime + cutime, hz);
+
+             Lisp_Object uptime = get_up_time ();
+             if (!NILP (uptime))
+               {
+                 Lisp_Object now = Ftime_convert (Qnil, hz);
+                 Lisp_Object boot = Ftime_subtract (now, uptime);
+                 Lisp_Object tstart = time_from_jiffies (start, hz, hz);
+                 Lisp_Object lstart =
+                   Ftime_convert (Ftime_add (boot, tstart), Qnil);
+                 attrs = Fcons (Fcons (Qstart, lstart), attrs);
+                 Lisp_Object etime =
+                   Ftime_convert (Ftime_subtract (uptime, tstart), Qnil);
+                 attrs = Fcons (Fcons (Qetime, etime), attrs);
+                 pcpu = (100.0 * (s_time + u_time)
+                         / (clocks_per_sec * float_time (etime)));
+                 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
+               }
+           }
+
          attrs = Fcons (Fcons (Qpri, make_fixnum (priority)), attrs);
          attrs = Fcons (Fcons (Qnice, make_fixnum (niceness)), attrs);
          attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (thcount)), attrs);
-         tnow = current_timespec ();
-         telapsed = get_up_time ();
-         tboot = timespec_sub (tnow, telapsed);
-         tstart = time_from_jiffies (start, clocks_per_sec);
-         tstart = timespec_add (tboot, tstart);
-         attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs);
          attrs = Fcons (Fcons (Qvsize, INT_TO_INTEGER (vsize / 1024)), attrs);
          attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (4 * rss)), attrs);
-         telapsed = timespec_sub (tnow, tstart);
-         attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
-         us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
-         pcpu = timespectod (us_time) / timespectod (telapsed);
-         attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
          pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
          if (pmem > 100)
            pmem = 100;
diff --git a/src/systime.h b/src/systime.h
index f3b1b2394d..41d728f1c2 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -92,6 +92,7 @@ extern bool list4_to_timespec (Lisp_Object, Lisp_Object, 
Lisp_Object,
                               Lisp_Object, struct timespec *);
 extern struct timespec lisp_time_argument (Lisp_Object);
 extern AVOID time_overflow (void);
+extern double float_time (Lisp_Object);
 extern void init_timefns (void);
 extern void syms_of_timefns (void);
 
diff --git a/src/timefns.c b/src/timefns.c
index 795a6484ce..9b5b090ba7 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -881,7 +881,7 @@ decode_lisp_time (Lisp_Object specified_time, bool 
decode_secs_only,
 
 /* Convert a Lisp timestamp SPECIFIED_TIME to double.
    Signal an error if unsuccessful.  */
-static double
+double
 float_time (Lisp_Object specified_time)
 {
   double t;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]