summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2022-03-04 19:21:38 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2022-03-04 19:29:05 -0800
commit2fbd48f733426824cb89b958378a52cfb053774c (patch)
tree79426b942d4901e0049837f29426ebf299181bcd /src
parentb19ec1be3c35b0ec231282ab51d0b320e2967052 (diff)
downloademacs-2fbd48f733426824cb89b958378a52cfb053774c.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/sysdep.c124
-rw-r--r--src/systime.h1
-rw-r--r--src/timefns.c2
3 files changed, 49 insertions, 78 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index c9101f94818..a266307588c 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 f3b1b2394da..41d728f1c29 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 795a6484ce9..9b5b090ba71 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;