summaryrefslogtreecommitdiff
path: root/src/sysdep.c
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/sysdep.c
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/sysdep.c')
-rw-r--r--src/sysdep.c124
1 files changed, 47 insertions, 77 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;