summaryrefslogtreecommitdiff
path: root/src/sysdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sysdep.c')
-rw-r--r--src/sysdep.c227
1 files changed, 101 insertions, 126 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 3356582de0c..8d1c3d0ca3c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <allocator.h>
#include <careadlinkat.h>
#include <ignore-value.h>
+#include <utimens.h>
#include "lisp.h"
#include "sysselect.h"
@@ -109,20 +110,6 @@ extern char *getwd (char *);
#include "syssignal.h"
#include "systime.h"
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-
-#ifndef HAVE_UTIMES
-#ifndef HAVE_STRUCT_UTIMBUF
-/* We want to use utime rather than utimes, but we couldn't find the
- structure declaration. We'll use the traditional one. */
-struct utimbuf {
- long actime;
- long modtime;
-};
-#endif
-#endif
static int emacs_get_tty (int, struct emacs_tty *);
static int emacs_set_tty (int, struct emacs_tty *, int);
@@ -2067,30 +2054,6 @@ perror (void)
#endif /* HPUX and not HAVE_PERROR */
/*
- * Gettimeofday. Simulate as much as possible. Only accurate
- * to nearest second. Emacs doesn't use tzp so ignore it for now.
- * Only needed when subprocesses are defined.
- */
-
-#ifndef HAVE_GETTIMEOFDAY
-#ifdef HAVE_TIMEVAL
-
-int
-gettimeofday (struct timeval *tp, struct timezone *tzp)
-{
- extern long time (long);
-
- tp->tv_sec = time ((long *)0);
- tp->tv_usec = 0;
- if (tzp != 0)
- tzp->tz_minuteswest = -1;
- return 0;
-}
-
-#endif
-#endif /* !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
-
-/*
* This function will go away as soon as all the stubs fixed. (fnf)
*/
@@ -2126,20 +2089,43 @@ closedir (DIR *dirp /* stream from opendir */)
#endif /* HAVE_DIRENT_H */
+/* Return a struct timeval that is roughly equivalent to T.
+ Use the least timeval not less than T.
+ Return an extremal value if the result would overflow. */
+struct timeval
+make_timeval (EMACS_TIME t)
+{
+ struct timeval tv;
+ tv.tv_sec = t.tv_sec;
+ tv.tv_usec = t.tv_nsec / 1000;
+
+ if (t.tv_nsec % 1000 != 0)
+ {
+ if (tv.tv_usec < 999999)
+ tv.tv_usec++;
+ else if (tv.tv_sec < TYPE_MAXIMUM (time_t))
+ {
+ tv.tv_sec++;
+ tv.tv_usec = 0;
+ }
+ }
+
+ return tv;
+}
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+ ATIME and MTIME, respectively.
+ FD must be either negative -- in which case it is ignored --
+ or a file descriptor that is open on FILE.
+ If FD is nonnegative, then FILE can be NULL. */
int
-set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
-{
-#ifdef HAVE_UTIMES
- struct timeval tv[2];
- tv[0] = atime;
- tv[1] = mtime;
- return utimes (filename, tv);
-#else /* not HAVE_UTIMES */
- struct utimbuf utb;
- utb.actime = EMACS_SECS (atime);
- utb.modtime = EMACS_SECS (mtime);
- return utime (filename, &utb);
-#endif /* not HAVE_UTIMES */
+set_file_times (int fd, const char *filename,
+ EMACS_TIME atime, EMACS_TIME mtime)
+{
+ struct timespec timespec[2];
+ timespec[0] = atime;
+ timespec[1] = mtime;
+ return fdutimens (fd, filename, timespec);
}
/* mkdir and rmdir functions, for systems which don't have them. */
@@ -2595,60 +2581,82 @@ list_system_processes (void)
#endif /* !defined (WINDOWSNT) */
#ifdef GNU_LINUX
-static void
-time_from_jiffies (unsigned long long tval, long hz,
- time_t *sec, unsigned *usec)
-{
- unsigned long long ullsec;
-
- *sec = tval / hz;
- ullsec = *sec;
- tval -= ullsec * hz;
- /* Careful: if HZ > 1 million, then integer division by it yields zero. */
- if (hz <= 1000000)
- *usec = tval * 1000000 / hz;
+static EMACS_TIME
+time_from_jiffies (unsigned long long tval, long hz)
+{
+ unsigned long long s = tval / hz;
+ unsigned long long frac = tval % hz;
+ int ns;
+ EMACS_TIME t;
+
+ if (TYPE_MAXIMUM (time_t) < s)
+ time_overflow ();
+ if (LONG_MAX - 1 <= ULLONG_MAX / EMACS_TIME_RESOLUTION
+ || frac <= ULLONG_MAX / EMACS_TIME_RESOLUTION)
+ ns = frac * EMACS_TIME_RESOLUTION / hz;
else
- *usec = tval / (hz / 1000000);
+ {
+ /* 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 / EMACS_TIME_RESOLUTION
+ + (hz % EMACS_TIME_RESOLUTION != 0));
+ ns = frac / hz_per_ns;
+ }
+
+ EMACS_SET_SECS_NSECS (t, s, ns);
+ return t;
}
static Lisp_Object
ltime_from_jiffies (unsigned long long tval, long hz)
{
- time_t sec;
- unsigned usec;
-
- time_from_jiffies (tval, hz, &sec, &usec);
-
- return list3 (make_number ((sec >> 16) & 0xffff),
- make_number (sec & 0xffff),
- make_number (usec));
+ EMACS_TIME t = time_from_jiffies (tval, hz);
+ return make_lisp_time (t);
}
-static void
-get_up_time (time_t *sec, unsigned *usec)
+static EMACS_TIME
+get_up_time (void)
{
FILE *fup;
+ EMACS_TIME up;
- *sec = *usec = 0;
+ EMACS_SET_SECS_NSECS (up, 0, 0);
BLOCK_INPUT;
fup = fopen ("/proc/uptime", "r");
if (fup)
{
- double uptime, idletime;
+ unsigned long long upsec, upfrac, idlesec, idlefrac;
+ int upfrac_start, upfrac_end, idlefrac_start, idlefrac_end;
- /* The numbers in /proc/uptime use C-locale decimal point, but
- we already set ourselves to the C locale (see `fixup_locale'
- in emacs.c). */
- if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
+ if (fscanf (fup, "%llu.%n%llu%n %llu.%n%llu%n",
+ &upsec, &upfrac_start, &upfrac, &upfrac_end,
+ &idlesec, &idlefrac_start, &idlefrac, &idlefrac_end)
+ == 4)
{
- *sec = uptime;
- *usec = (uptime - *sec) * 1000000;
+ if (TYPE_MAXIMUM (time_t) < upsec)
+ {
+ upsec = TYPE_MAXIMUM (time_t);
+ upfrac = EMACS_TIME_RESOLUTION - 1;
+ }
+ else
+ {
+ int upfraclen = upfrac_end - upfrac_start;
+ for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++)
+ upfrac *= 10;
+ for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--)
+ upfrac /= 10;
+ upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
+ }
+ EMACS_SET_SECS_NSECS (up, upsec, upfrac);
}
fclose (fup);
}
UNBLOCK_INPUT;
+
+ return up;
}
#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
@@ -2748,9 +2756,7 @@ 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;
- time_t sec;
- unsigned usec;
- EMACS_TIME tnow, tstart, tboot, telapsed;
+ EMACS_TIME tnow, tstart, tboot, telapsed, us_time;
double pcpu, pmem;
Lisp_Object attrs = Qnil;
Lisp_Object cmd_str, decoded_cmd, tem;
@@ -2873,35 +2879,18 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs);
attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
EMACS_GET_TIME (tnow);
- get_up_time (&sec, &usec);
- EMACS_SET_SECS (telapsed, sec);
- EMACS_SET_USECS (telapsed, usec);
+ telapsed = get_up_time ();
EMACS_SUB_TIME (tboot, tnow, telapsed);
- time_from_jiffies (start, clocks_per_sec, &sec, &usec);
- EMACS_SET_SECS (tstart, sec);
- EMACS_SET_USECS (tstart, usec);
+ tstart = time_from_jiffies (start, clocks_per_sec);
EMACS_ADD_TIME (tstart, tboot, tstart);
- attrs = Fcons (Fcons (Qstart,
- list3 (make_number
- ((EMACS_SECS (tstart) >> 16) & 0xffff),
- make_number
- (EMACS_SECS (tstart) & 0xffff),
- make_number
- (EMACS_USECS (tstart)))),
- attrs);
+ attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs);
attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
EMACS_SUB_TIME (telapsed, tnow, tstart);
- attrs = Fcons (Fcons (Qetime,
- list3 (make_number
- ((EMACS_SECS (telapsed) >> 16) & 0xffff),
- make_number
- (EMACS_SECS (telapsed) & 0xffff),
- make_number
- (EMACS_USECS (telapsed)))),
- attrs);
- time_from_jiffies (u_time + s_time, clocks_per_sec, &sec, &usec);
- pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
+ attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
+ us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
+ pcpu = (EMACS_TIME_TO_DOUBLE (us_time)
+ / EMACS_TIME_TO_DOUBLE (telapsed));
if (pcpu > 1.0)
pcpu = 1.0;
attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
@@ -3082,27 +3071,13 @@ system_process_attributes (Lisp_Object pid)
Qcstime
Are they available? */
- attrs = Fcons (Fcons (Qtime,
- list3 (make_number (pinfo.pr_time.tv_sec >> 16),
- make_number (pinfo.pr_time.tv_sec & 0xffff),
- make_number (pinfo.pr_time.tv_nsec))),
- attrs);
-
- attrs = Fcons (Fcons (Qctime,
- list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
- make_number (pinfo.pr_ctime.tv_sec & 0xffff),
- make_number (pinfo.pr_ctime.tv_nsec))),
- attrs);
-
+ attrs = Fcons (Fcons (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
+ attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), attrs);
attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
- attrs = Fcons (Fcons (Qstart,
- list3 (make_number (pinfo.pr_start.tv_sec >> 16),
- make_number (pinfo.pr_start.tv_sec & 0xffff),
- make_number (pinfo.pr_start.tv_nsec))),
- attrs);
+ attrs = Fcons (Fcons (Qstart, make_lisp_time (pinfo.pr_start)), attrs);
attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);