]> git.eshelyaron.com Git - emacs.git/commitdiff
Support higher-resolution time stamps.
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 22 Jun 2012 21:17:42 +0000 (14:17 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 22 Jun 2012 21:17:42 +0000 (14:17 -0700)
Fixes: debbugs:9000
53 files changed:
ChangeLog
admin/CPP-DEFINES
admin/ChangeLog
admin/merge-gnulib
configure.in
doc/lispref/ChangeLog
doc/lispref/os.texi
doc/lispref/processes.texi
etc/ChangeLog
etc/NEWS
lib-src/ChangeLog
lib-src/Makefile.in
lib-src/profile.c
lib/gnulib.mk
lisp/ChangeLog
lisp/calendar/time-date.el
lisp/emacs-lisp/timer.el
lisp/proced.el
m4/gnulib-comp.m4
src/ChangeLog
src/Makefile.in
src/alloc.c
src/atimer.c
src/buffer.c
src/buffer.h
src/dired.c
src/dispextern.h
src/dispnew.c
src/editfns.c
src/fileio.c
src/fns.c
src/gtkutil.c
src/image.c
src/keyboard.c
src/lisp.h
src/lread.c
src/msdos.c
src/nsterm.h
src/nsterm.m
src/process.c
src/process.h
src/sysdep.c
src/sysselect.h
src/systime.h
src/term.c
src/undo.c
src/w32.c
src/xdisp.c
src/xgselect.c
src/xgselect.h
src/xmenu.c
src/xselect.c
src/xterm.c

index 7ba49e1c39f953315cd0affa0ec5a7584e7a3b1a..c8a763899cca90ee1da42b8c89c9858093b91b9f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+       * configure.in (gl_ASSERT_NO_GNULIB_POSIXCHECK)
+       (gl_ASSERT_NO_GNULIB_TESTS, gl_INIT): Move these up earlier, so
+       that the new clock stuff doesn't clash with RSVG_LIBS.
+       (AC_CHECK_HEADERS): Don't check for sys/select.h, sys/time.h, utime.h,
+       as gnulib does that for us now.
+       (emacs_cv_struct_utimbuf, HAVE_STRUCT_UTIMBUF, HAVE_TIMEVAL)
+       (GETTIMEOFDAY_ONE_ARGUMENT): Remove; gnulib does these now.
+       (AC_CHECK_FUNCS): Remove utimes; no longer needed.
+       * lib/dtotimespec.c, lib/gettime.c, lib/gettimeofday.c, lib/pselect.c:
+       * lib/stat-time.h, lib/sys_select.in.h, lib/sys_time.in.h:
+       * lib/timespec-add.c, lib/timespec-sub.c, lib/timespec.h:
+       * lib/utimens.c, lib/utimens.h, m4/clock_time.m4, m4/gettime.m4:
+       * m4/gettimeofday.m4, m4/pselect.m4, m4/stat-time.m4:
+       * m4/sys_select_h.m4, m4/sys_socket_h.m4, m4/sys_time_h.m4:
+       * m4/timespec.m4, m4/utimbuf.m4, m4/utimens.m4, m4/utimes.m4:
+       New files, copied automatically from gnulib.
+       * lib/gnulib.mk, m4/gnulib-comp.m4: Merge from gnulib.
+
 2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
 
        Merge from gnulib.
index e032ef87a40027a212abf63f2e13b5c27978b837..70245a0804e6f170c19e4735134f884d8b088230 100644 (file)
@@ -160,11 +160,9 @@ HAVE_SYS_SYSTEMINFO_H
 HAVE_SYS_TIMEB_H
 HAVE_SYS_TIME_H
 HAVE_TCATTR
-HAVE_TIMEVAL
 HAVE_TM_ZONE
 HAVE_TZSET
 HAVE_UNISTD_H
-HAVE_UTIMES
 HAVE_UTIME_H
 HAVE_WINDOW_SYSTEM
 HAVE_WORKING_VFORK
index e3b35906ace6044073e9e78cdf944209013400ac..ec6448dbeee7b849722b3647d5a67eea76546afd 100644 (file)
@@ -1,3 +1,18 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+       * merge-gnulib (GNULIB_MODULES): Add dtotimespec, gettime,
+       gettimeofday, pselect, stat-time, sys_time, time, timespec-add,
+       timespec-sub, utimens.
+       (GNULIB_TOOL_FLAGS): Add --avoid=select --avoid=sigprocmask.
+       This trims down the gnulib import, from the very latest gnulib.
+       Emacs does its own implementation of 'select' and 'sigprocmask'
+       on Windows, and it assumes 'select' and 'sigprocmask' on non-Windows
+       hosts, so it doesn't need these modules.
+       Similarly, avoid errno, fcntl, fcntl-h, fstat, and sys_types, as
+       these gnulib modules are only for Windows porting and Emacs ports
+       to Windows in a different way.
+
 2012-06-13  Andreas Schwab  <schwab@linux-m68k.org>
 
        * make-emacs: Rename --union-type to --check-lisp-type.  Define
index 7f91b788f40bc98847b4ec14ac4e11796fe23f42..d33807551d6ab51ba1697a716ce599a30a2d05a6 100755 (executable)
@@ -28,16 +28,20 @@ GNULIB_URL=git://git.savannah.gnu.org/gnulib.git
 GNULIB_MODULES='
   alloca-opt
   careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
-  dtoastr dup2
-  filemode getloadavg getopt-gnu ignore-value intprops largefile lstat
-  manywarnings mktime pthread_sigmask readlink
-  socklen stdarg stdio strftime strtoimax strtoumax symlink sys_stat
+  dtoastr dtotimespec dup2
+  filemode getloadavg getopt-gnu gettime gettimeofday
+  ignore-value intprops largefile lstat
+  manywarnings mktime pselect pthread_sigmask readlink
+  socklen stat-time stdarg stdio strftime strtoimax strtoumax symlink sys_stat
+  sys_time time timespec-add timespec-sub utimens
   warnings
 '
 
 GNULIB_TOOL_FLAGS='
+  --avoid=errno --avoid=fcntl --avoid=fcntl-h --avoid=fstat
   --avoid=msvc-inval --avoid=msvc-nothrow
-  --avoid=raise --avoid=threadlib
+  --avoid=raise --avoid=select --avoid=sigprocmask --avoid=sys_types
+  --avoid=threadlib
   --conditional-dependencies --import --no-changelog --no-vc-files
   --makefile-name=gnulib.mk
 '
index bc78cd47141ae5eb6d0c4b30873a5a1bc4ac5689..cbd52b13b0b006fe30ef3a5057f2e7eaa985c438 100644 (file)
@@ -1069,6 +1069,13 @@ case $opsys in
 esac
 
 
+# Configure gnulib before invoking PKG_CHECK_MODULES, as the latter might
+# for example add -lrt to RSVG_LIBS, which would then cause gnulib to
+# incorrectly conclude that -lrt is not needed to link clock_gettime.
+gl_ASSERT_NO_GNULIB_POSIXCHECK
+gl_ASSERT_NO_GNULIB_TESTS
+gl_INIT
+
 AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
 
 dnl This function definition taken from Gnome 2.0
@@ -1211,26 +1218,6 @@ if test $ac_cv_have_decl_sys_siglist != yes; then
 fi
 AC_HEADER_SYS_WAIT
 
-dnl Some systems have utime.h but don't declare the struct anyplace.
-AC_CACHE_CHECK(for struct utimbuf, emacs_cv_struct_utimbuf,
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif]], [[static struct utimbuf x; x.actime = x.modtime;]])],
-  emacs_cv_struct_utimbuf=yes, emacs_cv_struct_utimbuf=no))
-if test $emacs_cv_struct_utimbuf = yes; then
-  AC_DEFINE(HAVE_STRUCT_UTIMBUF, 1, [Define to 1 if `struct utimbuf' is declared by <utime.h>.])
-fi
-
 dnl Check for speed_t typedef.
 AC_CACHE_CHECK(for speed_t, emacs_cv_speed_t,
   [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <termios.h>]], [[speed_t x = 1;]])],
@@ -1240,23 +1227,6 @@ if test $emacs_cv_speed_t = yes; then
           [Define to 1 if `speed_t' is declared by <termios.h>.])
 fi
 
-AC_CACHE_CHECK(for struct timeval, emacs_cv_struct_timeval,
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif]], [[static struct timeval x; x.tv_sec = x.tv_usec;]])],
-  emacs_cv_struct_timeval=yes, emacs_cv_struct_timeval=no))
-HAVE_TIMEVAL=$emacs_cv_struct_timeval
-if test $emacs_cv_struct_timeval = yes; then
-  AC_DEFINE(HAVE_TIMEVAL, 1, [Define to 1 if `struct timeval' is declared by <sys/time.h>.])
-fi
-
 AC_CACHE_CHECK(for struct exception, emacs_cv_struct_exception,
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]],
 [[static struct exception x; x.arg1 = x.arg2 = x.retval; x.name = ""; x.type = 1;]])],
@@ -3019,33 +2989,6 @@ if test $emacs_cv_localtime_cache = yes; then
            [Define to 1 if localtime caches TZ.])
 fi
 
-if test "x$HAVE_TIMEVAL" = xyes; then
-  AC_CHECK_FUNCS(gettimeofday)
-  if test $ac_cv_func_gettimeofday = yes; then
-    AC_CACHE_CHECK(whether gettimeofday can accept two arguments,
-                  emacs_cv_gettimeofday_two_arguments,
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif]],
-      [[struct timeval time;
-       gettimeofday (&time, 0);]])],
-      emacs_cv_gettimeofday_two_arguments=yes,
-      emacs_cv_gettimeofday_two_arguments=no)])
-    if test $emacs_cv_gettimeofday_two_arguments = no; then
-      AC_DEFINE(GETTIMEOFDAY_ONE_ARGUMENT, 1,
-               [Define to 1 if gettimeofday accepts only one argument.])
-    fi
-  fi
-fi
-
 ok_so_far=yes
 AC_CHECK_FUNC(socket, , ok_so_far=no)
 if test $ok_so_far = yes; then
@@ -3118,7 +3061,7 @@ case $opsys in
 esac
 
 dnl SIGIO exists, but the feature doesn't work in the way Emacs needs.
-dnl See eg <http://article.gmane.org/gmane.os.openbsd.ports/46831>. 
+dnl See eg <http://article.gmane.org/gmane.os.openbsd.ports/46831>.
 case $opsys in
   hpux* | irix6-5 | openbsd | sol2* | unixware )
     AC_DEFINE(BROKEN_SIGIO, 1, [Define if SIGIO should not be used.])
@@ -3376,11 +3319,6 @@ AC_SUBST(CYGWIN_OBJ)
 AC_SUBST(PRE_ALLOC_OBJ)
 AC_SUBST(POST_ALLOC_OBJ)
 
-# Configure gnulib here, now that we know LIBS.
-gl_ASSERT_NO_GNULIB_POSIXCHECK
-gl_ASSERT_NO_GNULIB_TESTS
-gl_INIT
-
 case "$opsys" in
   aix4-2) LD_SWITCH_SYSTEM_TEMACS="-Wl,-bnodelcsect" ;;
 
index 91c3617cff8fc0db66fc1edbae0691bacca44040..838617cf8669c86749a0e7e55eaa94f7ecf47b42 100644 (file)
@@ -1,3 +1,10 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+       * os.texi (Time of Day, Time Parsing, Processor Run Time, Idle Timers):
+       * processes.texi (System Processes):
+       Time stamp resolution is now picosecond, not microsecond.
+
 2012-06-21  Glenn Morris  <rgm@gnu.org>
 
        * Makefile.in: Rename infodir to buildinfodir throughout.  (Bug#11737)
index e604d92e69063ec4d5400d6360eb9312f6f2c8dc..6431ac8beadf06a4f7cf1aa9bdfa9d90da6ba075 100644 (file)
@@ -1166,7 +1166,9 @@ The value may be a floating point number.
 zone.
 
 @cindex epoch
-  Most of these functions represent time as a list of either three
+  Most of these functions represent time as a list of either four
+integers, @code{(@var{sec-high} @var{sec-low} @var{microsec}
+@var{picosec})}, or of three
 integers, @code{(@var{sec-high} @var{sec-low} @var{microsec})}, or of
 two integers, @code{(@var{sec-high} @var{sec-low})}.  The integers
 @var{sec-high} and @var{sec-low} give the high and low bits of an
@@ -1181,12 +1183,15 @@ is the number of seconds from the @dfn{epoch} (0:00 January 1, 1970
 UTC) to the specified time.  The third list element @var{microsec}, if
 present, gives the number of microseconds from the start of that
 second to the specified time.
+Similarly, the fourth list element @var{picosec}, if present, gives
+the number of picoseconds from the start of that microsecond to the
+specified time.
 
   The return value of @code{current-time} represents time using three
-integers, while the timestamps in the return value of
-@code{file-attributes} use two integers (@pxref{Definition of
+integers, as do the timestamps in the return value of
+@code{file-attributes} (@pxref{Definition of
 file-attributes}).  In function arguments, e.g.@: the @var{time-value}
-argument to @code{current-time-string}, both two- and three-integer
+argument to @code{current-time-string}, two-, three-, and four-integer
 lists are accepted.  You can convert times from the list
 representation into standard human-readable strings using
 @code{current-time}, or to other forms using the @code{decode-time}
@@ -1216,9 +1221,12 @@ The argument @var{time-value}, if given, specifies a time to format
 @end defun
 
 @defun current-time
-This function returns the current time, represented as a list of three
-integers @code{(@var{sec-high} @var{sec-low} @var{microsec})}.  On
-systems with only one-second time resolutions, @var{microsec} is 0.
+This function returns the current time, represented as a list of four
+integers @code{(@var{sec-high} @var{sec-low} @var{microsec} @var{picosec})}.
+These integers have trailing zeros on systems that return time with
+lower resolutions.  On all current machines @var{picosec} is a
+multiple of 1000, but this may change as higher-resolution clocks
+become available.
 @end defun
 
 @defun float-time &optional time-value
@@ -1259,7 +1267,7 @@ time zone.
 @node Time Conversion
 @section Time Conversion
 
-  These functions convert time values (lists of two or three integers,
+  These functions convert time values (lists of two to four integers,
 as explained in the previous section) into calendrical information and
 vice versa.
 
@@ -1410,8 +1418,6 @@ This stands for a newline.
 This stands for the nanoseconds (000000000-999999999).  To ask for
 fewer digits, use @samp{%3N} for milliseconds, @samp{%6N} for
 microseconds, etc.  Any excess digits are discarded, without rounding.
-Currently Emacs time stamps are at best microsecond resolution so the
-last three digits generated by plain @samp{%N} are always zero.
 @item %p
 This stands for @samp{AM} or @samp{PM}, as appropriate.
 @item %r
@@ -1563,18 +1569,9 @@ When called interactively, it prints the uptime in the echo area.
 
 @defun get-internal-run-time
 This function returns the processor run time used by Emacs as a list
-of three integers: @code{(@var{high} @var{low} @var{microsec})}.  The
-integers @var{high} and @var{low} combine to give the number of
-seconds, which is
-@ifnottex
-@var{high} * 2**16 + @var{low}.
-@end ifnottex
-@tex
-$high*2^{16}+low$.
-@end tex
-
-The third element, @var{microsec}, gives the microseconds (or 0 for
-systems that return time with the resolution of only one second).
+of four integers: @code{(@var{high} @var{low} @var{microsec}
+@var{picosec})}, using the same format as @code{current-time}
+(@pxref{Time of Day}).
 
 Note that the time returned by this function excludes the time Emacs
 was not using the processor, and if the Emacs process has several
@@ -1817,10 +1814,9 @@ set up to repeat will subsequently run another time, one by one.
 
 @defun current-idle-time
 If Emacs is idle, this function returns the length of time Emacs has
-been idle, as a list of three integers: @code{(@var{sec-high}
-@var{sec-low} @var{microsec})}, where @var{high} and @var{low} are the
-high and low bits for the number of seconds and @var{microsec} is the
-additional number of microseconds (@pxref{Time of Day}).
+been idle, as a list of four integers: @code{(@var{sec-high}
+@var{sec-low} @var{microsec} @var{picosec})}, using the same format as
+@code{current-time} (@pxref{Time of Day}).
 
 When Emacs is not idle, @code{current-idle-time} returns @code{nil}.
 This is a convenient way to test whether Emacs is idle.
index 34b62a48329c069ccc555dc6f78fd73ff4dbd263..d1bfa0e936d9ab9ffcdcb87830931e4d7b775c34 100644 (file)
@@ -1770,7 +1770,7 @@ faults for all the child processes of the given process.
 @item utime
 Time spent by the process in the user context, for running the
 application's code.  The corresponding @var{value} is in the
-@w{@code{(@var{high} @var{low} @var{microsec})}} format, the same
+@w{@code{(@var{high} @var{low} @var{microsec} @var{picosec})}} format, the same
 format used by functions @code{current-time} (@pxref{Time of Day,
 current-time}) and @code{file-attributes} (@pxref{File Attributes}).
 
@@ -1801,12 +1801,12 @@ The number of threads in the process.
 
 @item start
 The time when the process was started, in the same
-@w{@code{(@var{high} @var{low} @var{microsec})}} format used by
+@w{@code{(@var{high} @var{low} @var{microsec} @var{picosec})}} format used by
 @code{current-time} and by @code{file-attributes}.
 
 @item etime
 The time elapsed since the process started, in the @w{@code{(@var{high}
-@var{low} @var{microsec})}} format.
+@var{low} @var{microsec} @var{picosec})}} format.
 
 @item vsize
 The virtual memory size of the process, measured in kilobytes.
index 3fd2d6bd92ab2c9b6418a2a8fa33ae8766be302e..6901077fbe0a694cd50e754d50bb917568c2d544 100644 (file)
@@ -1,3 +1,8 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+       * NEWS: Mention addition of picoseconds to time stamp format.
+
 2012-06-13  Deniz Dogan  <deniz@dogan.se>
 
        * tutorials/TUTORIAL.sv: Fix grammar and a couple of typos.
index 82c2660a3c77f2db03b4042d41eaef9e490d694b..054700352af501dc82d70f6e90dfa64f5e4e937c 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -64,6 +64,13 @@ been adding them there, put them somewhere else, eg site-lisp.
 \f
 * Changes in Emacs 24.2
 
+** The function `current-time' now returns extended-format time stamps
+(HIGH LOW USEC PSEC) that use picosecond resolution; the PSEC
+component is new.  PSEC is typically a multiple of 1000 on current
+machines.  Other functions that use this format, such as
+file-attributes and format-time-string, have been changed accordingly.
+Old-format time stamps are still accepted.
+
 ** New functions `system-users', `system-groups' return lists of the user
 name, group names known to the system (where possible).
 
index 68a8c37c2fb724fd2896a2191d987eb820b0b6ff..11f68cebf14311b434ae2fd0c2c29fd1da8f7710 100644 (file)
@@ -1,3 +1,13 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+       * Makefile.in (LIB_CLOCK_GETTIME): New macro.
+       (profile${EXEEXT}): Use it.
+       * profile.c: Include inttyeps.h, intprops.h.
+       (time_string): Size conservatively; do not guess size.
+       (get_time): Now prints nanoseconds.
+       (gettimeofday): Remove replacement function; gnulib now does this.
+
 2012-06-08  Andreas Schwab  <schwab@linux-m68k.org>
 
        * make-docfile.c (search_lisp_doc_at_eol): Unget last read
index 2df22d9f7d83bde3287325fc80eafa6567b0a1a8..a325fc18aac19e2dee3796fc8fc38a6086703492 100644 (file)
@@ -159,6 +159,8 @@ LIBHESIOD=@LIBHESIOD@
 LIBRESOLV=@LIBRESOLV@
 ## -llockfile if HAVE_LIBLOCKFILE or -lmail if HAVE_LIBMAIL
 LIBS_MAIL=@LIBS_MAIL@
+## empty or -lrt or -lposix4 if HAVE_CLOCK_GETTIME
+LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
 
 ## Extra libraries to use when linking movemail.
 LIBS_MOVE = $(LIBS_MAIL) $(KRB4LIB) $(DESLIB) $(KRB5LIB) $(CRYPTOLIB) \
@@ -309,7 +311,8 @@ ctags${EXEEXT}: etags${EXEEXT}
          regex.o $(LOADLIBES) -o ctags
 
 profile${EXEEXT}: ${srcdir}/profile.c ../src/config.h
-       $(CC) ${ALL_CFLAGS} ${srcdir}/profile.c $(LOADLIBES) -o profile
+       $(CC) ${ALL_CFLAGS} ${srcdir}/profile.c \
+         $(LOADLIBES) $(LIB_CLOCK_GETTIME) -o profile
 
 make-docfile${EXEEXT}: ${srcdir}/make-docfile.c ../src/config.h
        $(CC) ${ALL_CFLAGS} ${srcdir}/make-docfile.c $(LOADLIBES) \
index 8ed4f3189748e6e119bfc9143e88a0f84e1e27c4..3e642237c6bf98da3d20b147f8f44ee823b63387 100644 (file)
@@ -29,12 +29,17 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
  **  operations: reset_watch, get_time
  */
 #include <config.h>
+
+#include <inttypes.h>
 #include <stdio.h>
+
+#include <intprops.h>
 #include <systime.h>
 
 static EMACS_TIME TV1, TV2;
 static int watch_not_started = 1; /* flag */
-static char time_string[30];
+static char time_string[INT_STRLEN_BOUND (uintmax_t) + sizeof "."
+                       + LOG10_EMACS_TIME_RESOLUTION];
 
 /* Reset the stopwatch to zero.  */
 
@@ -46,36 +51,23 @@ reset_watch (void)
 }
 
 /* This call returns the time since the last reset_watch call.  The time
-   is returned as a string with the format  <seconds>.<micro-seconds>
+   is returned as a string with the format  <seconds>.<nanoseconds>
    If reset_watch was not called yet, exit.  */
 
 static char *
 get_time (void)
 {
+  uintmax_t s;
+  int ns;
   if (watch_not_started)
     exit (EXIT_FAILURE);  /* call reset_watch first ! */
   EMACS_GET_TIME (TV2);
   EMACS_SUB_TIME (TV2, TV2, TV1);
-  sprintf (time_string, "%lu.%06lu", (unsigned long)EMACS_SECS (TV2), (unsigned long)EMACS_USECS (TV2));
+  s = EMACS_SECS (TV2);
+  ns = EMACS_NSECS (TV2);
+  sprintf (time_string, "%"PRIuMAX".%0*d", s, LOG10_EMACS_TIME_RESOLUTION, ns);
   return time_string;
 }
-
-#if ! defined (HAVE_GETTIMEOFDAY) && defined (HAVE_TIMEVAL)
-
-/* ARGSUSED */
-gettimeofday (tp, tzp)
-     struct timeval *tp;
-     struct timezone *tzp;
-{
-  extern long time ();
-
-  tp->tv_sec = time ((long *)0);
-  tp->tv_usec = 0;
-  if (tzp != 0)
-    tzp->tz_minuteswest = -1;
-}
-
-#endif
 \f
 int
 main (void)
index 3572e5bc170d634e9791164c319502778bd20c3c..20aa19d93a5784d7d445c8325e07974f4a0aa13d 100644 (file)
@@ -21,7 +21,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=msvc-inval --avoid=msvc-nothrow --avoid=raise --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dup2 filemode getloadavg getopt-gnu ignore-value intprops largefile lstat manywarnings mktime pthread_sigmask readlink socklen stdarg stdio strftime strtoimax strtoumax symlink sys_stat warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=errno --avoid=fcntl --avoid=fcntl-h --avoid=fstat --avoid=msvc-inval --avoid=msvc-nothrow --avoid=raise --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask readlink socklen stat-time stdarg stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timespec-add timespec-sub utimens warnings
 
 
 MOSTLYCLEANFILES += core *.stackdump
@@ -123,6 +123,12 @@ EXTRA_libgnu_a_SOURCES += ftoastr.c
 
 ## end   gnulib module dtoastr
 
+## begin gnulib module dtotimespec
+
+libgnu_a_SOURCES += dtotimespec.c
+
+## end   gnulib module dtotimespec
+
 ## begin gnulib module dup2
 
 
@@ -184,6 +190,21 @@ libgnu_a_SOURCES += gettext.h
 endif
 ## end   gnulib module gettext-h
 
+## begin gnulib module gettime
+
+libgnu_a_SOURCES += gettime.c
+
+## end   gnulib module gettime
+
+## begin gnulib module gettimeofday
+
+
+EXTRA_DIST += gettimeofday.c
+
+EXTRA_libgnu_a_SOURCES += gettimeofday.c
+
+## end   gnulib module gettimeofday
+
 ## begin gnulib module ignore-value
 
 
@@ -269,6 +290,15 @@ EXTRA_DIST += pathmax.h
 
 ## end   gnulib module pathmax
 
+## begin gnulib module pselect
+
+
+EXTRA_DIST += pselect.c
+
+EXTRA_libgnu_a_SOURCES += pselect.c
+
+## end   gnulib module pselect
+
 ## begin gnulib module pthread_sigmask
 
 
@@ -329,17 +359,6 @@ EXTRA_DIST += signal.in.h
 
 ## end   gnulib module signal-h
 
-## begin gnulib module sigprocmask
-
-if gl_GNULIB_ENABLED_sigprocmask
-
-endif
-EXTRA_DIST += sigprocmask.c
-
-EXTRA_libgnu_a_SOURCES += sigprocmask.c
-
-## end   gnulib module sigprocmask
-
 ## begin gnulib module snippet/_Noreturn
 
 # Because this Makefile snippet defines a variable used by other
@@ -432,6 +451,13 @@ EXTRA_libgnu_a_SOURCES += stat.c
 
 ## end   gnulib module stat
 
+## begin gnulib module stat-time
+
+
+EXTRA_DIST += stat-time.h
+
+## end   gnulib module stat-time
+
 ## begin gnulib module stdalign
 
 BUILT_SOURCES += $(STDALIGN_H)
@@ -871,6 +897,40 @@ EXTRA_libgnu_a_SOURCES += symlink.c
 
 ## end   gnulib module symlink
 
+## begin gnulib module sys_select
+
+BUILT_SOURCES += sys/select.h
+
+# We need the following in order to create <sys/select.h> when the system
+# doesn't have one that works with the given compiler.
+sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+       $(AM_V_at)$(MKDIR_P) sys
+       $(AM_V_GEN)rm -f $@-t $@ && \
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+             -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+             -e 's|@''NEXT_SYS_SELECT_H''@|$(NEXT_SYS_SELECT_H)|g' \
+             -e 's|@''HAVE_SYS_SELECT_H''@|$(HAVE_SYS_SELECT_H)|g' \
+             -e 's/@''GNULIB_PSELECT''@/$(GNULIB_PSELECT)/g' \
+             -e 's/@''GNULIB_SELECT''@/$(GNULIB_SELECT)/g' \
+             -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
+             -e 's|@''HAVE_PSELECT''@|$(HAVE_PSELECT)|g' \
+             -e 's|@''REPLACE_PSELECT''@|$(REPLACE_PSELECT)|g' \
+             -e 's|@''REPLACE_SELECT''@|$(REPLACE_SELECT)|g' \
+             -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+             -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+             < $(srcdir)/sys_select.in.h; \
+       } > $@-t && \
+       mv $@-t $@
+MOSTLYCLEANFILES += sys/select.h sys/select.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_select.in.h
+
+## end   gnulib module sys_select
+
 ## begin gnulib module sys_stat
 
 BUILT_SOURCES += sys/stat.h
@@ -933,30 +993,39 @@ EXTRA_DIST += sys_stat.in.h
 
 ## end   gnulib module sys_stat
 
-## begin gnulib module sys_types
+## begin gnulib module sys_time
 
-BUILT_SOURCES += sys/types.h
+BUILT_SOURCES += sys/time.h
 
-# We need the following in order to create <sys/types.h> when the system
+# We need the following in order to create <sys/time.h> when the system
 # doesn't have one that works with the given compiler.
-sys/types.h: sys_types.in.h $(top_builddir)/config.status
+sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
        $(AM_V_at)$(MKDIR_P) sys
        $(AM_V_GEN)rm -f $@-t $@ && \
        { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+             -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \
              -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
              -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
              -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
-             -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \
-             -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
-             < $(srcdir)/sys_types.in.h; \
+             -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \
+             -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
+             -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
+             -e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \
+             -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
+             -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \
+             -e 's/@''REPLACE_STRUCT_TIMEVAL''@/$(REPLACE_STRUCT_TIMEVAL)/g' \
+             -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+             -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+             -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+             < $(srcdir)/sys_time.in.h; \
        } > $@-t && \
        mv $@-t $@
-MOSTLYCLEANFILES += sys/types.h sys/types.h-t
+MOSTLYCLEANFILES += sys/time.h sys/time.h-t
 
-EXTRA_DIST += sys_types.in.h
+EXTRA_DIST += sys_time.in.h
 
-## end   gnulib module sys_types
+## end   gnulib module sys_time
 
 ## begin gnulib module time
 
@@ -1009,6 +1078,25 @@ EXTRA_libgnu_a_SOURCES += time_r.c
 
 ## end   gnulib module time_r
 
+## begin gnulib module timespec
+
+
+EXTRA_DIST += timespec.h
+
+## end   gnulib module timespec
+
+## begin gnulib module timespec-add
+
+libgnu_a_SOURCES += timespec-add.c
+
+## end   gnulib module timespec-add
+
+## begin gnulib module timespec-sub
+
+libgnu_a_SOURCES += timespec-sub.c
+
+## end   gnulib module timespec-sub
+
 ## begin gnulib module u64
 
 
@@ -1166,6 +1254,14 @@ EXTRA_DIST += unistd.in.h
 
 ## end   gnulib module unistd
 
+## begin gnulib module utimens
+
+libgnu_a_SOURCES += utimens.c
+
+EXTRA_DIST += utimens.h
+
+## end   gnulib module utimens
+
 ## begin gnulib module verify
 
 if gl_GNULIB_ENABLED_verify
index 42342c60386291e5e6c4acde1a1bffa6904455be..f99b3e4d32a673254e300df57d0c93dc3a1a266f 100644 (file)
@@ -1,3 +1,26 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+
+       * calendar/time-date.el (with-decoded-time-value): New arg
+       PICO-SYMBOL in VARLIST.  It's optional, for backward compatibility.
+       (encode-time-value): New optional arg PICO.  New type 3.
+       (time-to-seconds) [!float-time]: Support the new picoseconds
+       component if it's used.
+       (seconds-to-time, time-subtract, time-add):
+       Support ps-resolution time stamps as well.
+
+       * emacs-lisp/timer.el (timer): New component psecs.  All uses changed.
+       (timerp): Timer vectors now have length 9, not 8.
+       (timer--time): Support new-style (4-part) time stamps.
+       (timer-next-integral-multiple-of-time): Time stamps now have
+       picosecond resolution, so take a bit more care about rounding.
+       (timer-relative-time, timer-inc-time): New optional arg psecs.
+       (timer-set-time-with-usecs): Set psecs to 0.
+       (timer--activate): Check psecs component, too.
+
+       * proced.el (proced-time-lessp): Support ps-resolution stamps.
+
 2012-06-22  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * icomplete.el (icomplete-minibuffer-setup, icomplete-completions):
index 46e38ae46a80104ff1ccaf5cd9281f612e3ea276..38b766084c91ecd9b2b42d217e89bff21631cb79 100644 (file)
 
 ;;; Commentary:
 
-;; Time values come in three formats.  The oldest format is a cons
+;; Time values come in several formats.  The oldest format is a cons
 ;; cell of the form (HIGH . LOW).  This format is obsolete, but still
-;; supported.  The two other formats are the lists (HIGH LOW) and
-;; (HIGH LOW MICRO).  The first two formats specify HIGH * 2^16 + LOW
-;; seconds; the third format specifies HIGH * 2^16 + LOW + MICRO /
-;; 1000000 seconds.  We should have 0 <= MICRO < 1000000 and 0 <= LOW
-;; < 2^16.  If the time value represents a point in time, then HIGH is
-;; nonnegative.  If the time value is a time difference, then HIGH can
-;; be negative as well.  The macro `with-decoded-time-value' and the
+;; supported.  The other formats are the lists (HIGH LOW), (HIGH LOW
+;; USEC), and (HIGH LOW USEC PSEC).  These formats specify the time
+;; value equal to HIGH * 2^16 + LOW + USEC * 10^-6 + PSEC * 10^-12
+;; seconds, where missing components are treated as zero.  HIGH can be
+;; negative, either because the value is a time difference, or because
+;; the machine supports negative time stamps that fall before the
+;; epoch.  The macro `with-decoded-time-value' and the
 ;; function `encode-time-value' make it easier to deal with these
 ;; three formats.  See `time-subtract' for an example of how to use
 ;; them.
 The value of the last form in BODY is returned.
 
 Each element of the list VARLIST is a list of the form
-\(HIGH-SYMBOL LOW-SYMBOL MICRO-SYMBOL [TYPE-SYMBOL] TIME-VALUE).
+\(HIGH-SYMBOL LOW-SYMBOL MICRO-SYMBOL [PICO-SYMBOL [TYPE-SYMBOL]] TIME-VALUE).
 The time value TIME-VALUE is decoded and the result it bound to
 the symbols HIGH-SYMBOL, LOW-SYMBOL and MICRO-SYMBOL.
+The optional PICO-SYMBOL is bound to the picoseconds part.
 
 The optional TYPE-SYMBOL is bound to the type of the time value.
 Type 0 is the cons cell (HIGH . LOW), type 1 is the list (HIGH
-LOW), and type 2 is the list (HIGH LOW MICRO)."
+LOW), type 2 is the list (HIGH LOW MICRO), and type 3 is the
+list (HIGH LOW MICRO PICO)."
   (declare (indent 1)
           (debug ((&rest (symbolp symbolp symbolp &or [symbolp form] form))
                   body)))
@@ -59,6 +61,8 @@ LOW), and type 2 is the list (HIGH LOW MICRO)."
             (high (pop elt))
             (low (pop elt))
             (micro (pop elt))
+            (pico (unless (<= (length elt) 2)
+                    (pop elt)))
             (type (unless (eq (length elt) 1)
                     (pop elt)))
             (time-value (car elt))
@@ -66,28 +70,44 @@ LOW), and type 2 is the list (HIGH LOW MICRO)."
        `(let* ,(append `((,gensym ,time-value)
                          (,high (pop ,gensym))
                          ,low ,micro)
+                       (when pico `(,pico))
                        (when type `(,type)))
           (if (consp ,gensym)
               (progn
                 (setq ,low (pop ,gensym))
                 (if ,gensym
-                    ,(append `(setq ,micro (car ,gensym))
-                             (when type `(,type 2)))
+                    (progn
+                      (setq ,micro (car ,gensym))
+                      ,(cond (pico
+                              `(if (cdr ,gensym)
+                                   ,(append `(setq ,pico (cadr ,gensym))
+                                            (when type `(,type 3)))
+                                 ,(append `(setq ,pico 0)
+                                          (when type `(,type 2)))))
+                             (type
+                              `(setq type 2))))
                   ,(append `(setq ,micro 0)
+                           (when pico `(,pico 0))
                            (when type `(,type 1)))))
             ,(append `(setq ,low ,gensym ,micro 0)
+                     (when pico `(,pico 0))
                      (when type `(,type 0))))
           (with-decoded-time-value ,varlist ,@body)))
     `(progn ,@body)))
 
-(defun encode-time-value (high low micro type)
-  "Encode HIGH, LOW, and MICRO into a time value of type TYPE.
+(defun encode-time-value (high low micro pico &optional type)
+  "Encode HIGH, LOW, MICRO, and PICO into a time value of type TYPE.
 Type 0 is the cons cell (HIGH . LOW), type 1 is the list (HIGH LOW),
-and type 2 is the list (HIGH LOW MICRO)."
+type 2 is (HIGH LOW MICRO), and type 3 is (HIGH LOW MICRO PICO).
+
+For backward compatibility, if only four arguments are given,
+it is assumed that PICO was omitted and should be treated as zero."
   (cond
    ((eq type 0) (cons high low))
    ((eq type 1) (list high low))
-   ((eq type 2) (list high low micro))))
+   ((eq type 2) (list high low micro))
+   ((eq type 3) (list high low micro pico))
+   ((null type) (encode-time-value high low micro 0 pico))))
 
 (autoload 'parse-time-string "parse-time")
 (autoload 'timezone-make-date-arpa-standard "timezone")
@@ -125,28 +145,45 @@ If DATE lacks timezone information, GMT is assumed."
            (subrp (symbol-function 'float-time)))
       (defun time-to-seconds (time)
         "Convert time value TIME to a floating point number."
-        (with-decoded-time-value ((high low micro time))
+        (with-decoded-time-value ((high low micro pico type time))
           (+ (* 1.0 high 65536)
              low
-             (/ micro 1000000.0))))))
+            (/ (+ (* micro 1e6) pico) 1e12))))))
 
 ;;;###autoload
 (defun seconds-to-time (seconds)
   "Convert SECONDS (a floating point number) to a time value."
-  (list (floor seconds 65536)
-       (floor (mod seconds 65536))
-       (floor (* (- seconds (ffloor seconds)) 1000000))))
+  (let* ((usec (* 1000000 (mod seconds 1)))
+        (ps (round (* 1000000 (mod usec 1))))
+        (us (floor usec))
+        (lo (floor (mod seconds 65536)))
+        (hi (floor seconds 65536)))
+    (if (eq ps 1000000)
+       (progn
+         (setq ps 0)
+         (setq us (1+ us))
+         (if (eq us 1000000)
+             (progn
+               (setq us 0)
+               (setq lo (1+ lo))
+               (if (eq lo 65536)
+                   (progn
+                     (setq lo 0)
+                     (setq hi (1+ hi))))))))
+    (list hi lo us ps)))
 
 ;;;###autoload
 (defun time-less-p (t1 t2)
   "Return non-nil if time value T1 is earlier than time value T2."
-  (with-decoded-time-value ((high1 low1 micro1 t1)
-                           (high2 low2 micro2 t2))
+  (with-decoded-time-value ((high1 low1 micro1 pico1 type1 t1)
+                           (high2 low2 micro2 pico2 type2 t2))
     (or (< high1 high2)
        (and (= high1 high2)
             (or (< low1 low2)
                 (and (= low1 low2)
-                     (< micro1 micro2)))))))
+                     (or (< micro1 micro2)
+                         (and (= micro1 micro2)
+                              (< pico1 pico2)))))))))
 
 ;;;###autoload
 (defun days-to-time (days)
@@ -173,36 +210,44 @@ TIME should be either a time value or a date-time string."
 (defun time-subtract (t1 t2)
   "Subtract two time values, T1 minus T2.
 Return the difference in the format of a time value."
-  (with-decoded-time-value ((high low micro type t1)
-                           (high2 low2 micro2 type2 t2))
+  (with-decoded-time-value ((high low micro pico type t1)
+                           (high2 low2 micro2 pico2 type2 t2))
     (setq high (- high high2)
          low (- low low2)
          micro (- micro micro2)
+         pico (- pico pico2)
          type (max type type2))
+    (when (< pico 0)
+      (setq micro (1- micro)
+           pico (+ pico 1000000)))
     (when (< micro 0)
       (setq low (1- low)
            micro (+ micro 1000000)))
     (when (< low 0)
       (setq high (1- high)
            low (+ low 65536)))
-    (encode-time-value high low micro type)))
+    (encode-time-value high low micro pico type)))
 
 ;;;###autoload
 (defun time-add (t1 t2)
   "Add two time values T1 and T2.  One should represent a time difference."
-  (with-decoded-time-value ((high low micro type t1)
-                           (high2 low2 micro2 type2 t2))
+  (with-decoded-time-value ((high low micro pico type t1)
+                           (high2 low2 micro2 pico2 type2 t2))
     (setq high (+ high high2)
          low (+ low low2)
          micro (+ micro micro2)
+         pico (+ pico pico2)
          type (max type type2))
+    (when (>= pico 1000000)
+      (setq micro (1+ micro)
+           pico (- pico 1000000)))
     (when (>= micro 1000000)
       (setq low (1+ low)
            micro (- micro 1000000)))
     (when (>= low 65536)
       (setq high (1+ high)
            low (- low 65536)))
-    (encode-time-value high low micro type)))
+    (encode-time-value high low micro pico type)))
 
 ;;;###autoload
 (defun date-to-day (date)
index 0b8480441c31f833e1eb274b03a5044d545184e8..eab96fe202a986587539fbd240b58c2f0926060e 100644 (file)
@@ -28,7 +28,7 @@
 ;;; Code:
 
 ;; Layout of a timer vector:
-;; [triggered-p high-seconds low-seconds usecs repeat-delay
+;; [triggered-p high-seconds low-seconds usecs psecs repeat-delay
 ;;  function args idle-delay]
 ;; triggered-p is nil if the timer is active (waiting to be triggered),
 ;;  t if it is inactive ("already triggered", in theory)
             (:type vector)
             (:conc-name timer--))
   (triggered t)
-  high-seconds low-seconds usecs repeat-delay function args idle-delay)
+  high-seconds low-seconds usecs psecs repeat-delay function args idle-delay)
 
 (defun timerp (object)
   "Return t if OBJECT is a timer."
-  (and (vectorp object) (= (length object) 8)))
+  (and (vectorp object) (= (length object) 9)))
 
 ;; Pseudo field `time'.
 (defun timer--time (timer)
   (list (timer--high-seconds timer)
         (timer--low-seconds timer)
-        (timer--usecs timer)))
+       (timer--usecs timer)
+       (timer--psecs timer)))
 
 (gv-define-simple-setter timer--time
   (lambda (timer time)
     (or (timerp timer) (error "Invalid timer"))
     (setf (timer--high-seconds timer) (pop time))
-    (setf (timer--low-seconds timer)
-          (if (consp time) (car time) time))
-    (setf (timer--usecs timer) (or (and (consp time) (consp (cdr time))
-                                           (cadr time))
-                                      0))))
+    (let ((low time) (usecs 0) (psecs 0))
+      (if (consp time)
+         (progn
+           (setq low (pop time))
+           (if time
+               (progn
+                 (setq usecs (pop time))
+                 (if time
+                     (setq psecs (car time)))))))
+      (setf (timer--low-seconds timer) low)
+      (setf (timer--usecs timer) usecs)
+      (setf (timer--psecs timer) psecs))))
 
 
 (defun timer-set-time (timer time &optional delta)
@@ -77,7 +85,7 @@ fire repeatedly that many seconds apart."
 (defun timer-set-idle-time (timer secs &optional repeat)
   "Set the trigger idle time of TIMER to SECS.
 SECS may be an integer, floating point number, or the internal
-time format (HIGH LOW USECS) returned by, e.g., `current-idle-time'.
+time format returned by, e.g., `current-idle-time'.
 If optional third argument REPEAT is non-nil, make the timer
 fire each time Emacs is idle for that many seconds."
   (if (consp secs)
@@ -91,41 +99,46 @@ fire each time Emacs is idle for that many seconds."
   "Yield the next value after TIME that is an integral multiple of SECS.
 More precisely, the next value, after TIME, that is an integral multiple
 of SECS seconds since the epoch.  SECS may be a fraction."
-  (let ((time-base (ash 1 16)))
-    ;; Use floating point, taking care to not lose precision.
-    (let* ((float-time-base (float time-base))
-          (million 1000000.0)
-          (time-usec (+ (* million
-                           (+ (* float-time-base (nth 0 time))
-                              (nth 1 time)))
-                        (nth 2 time)))
-          (secs-usec (* million secs))
-          (mod-usec (mod time-usec secs-usec))
-          (next-usec (+ (- time-usec mod-usec) secs-usec))
-          (time-base-million (* float-time-base million)))
-      (list (floor next-usec time-base-million)
-           (floor (mod next-usec time-base-million) million)
-           (floor (mod next-usec million))))))
-
-(defun timer-relative-time (time secs &optional usecs)
-  "Advance TIME by SECS seconds and optionally USECS microseconds.
-SECS may be either an integer or a floating point number."
+  (let* ((trillion 1e12)
+        (time-sec (+ (nth 1 time)
+                     (* 65536.0 (nth 0 time))))
+        (delta-sec (mod (- time-sec) secs))
+        (next-sec (+ time-sec (ffloor delta-sec)))
+        (next-sec-psec (ffloor (* trillion (mod delta-sec 1))))
+        (sub-time-psec (+ (or (nth 3 time) 0)
+                          (* 1e6 (nth 2 time))))
+        (psec-diff (- sub-time-psec next-sec-psec)))
+    (if (and (<= next-sec time-sec) (< 0 psec-diff))
+       (setq next-sec-psec (+ sub-time-psec
+                              (mod (- psec-diff) (* trillion secs)))))
+    (setq next-sec (+ next-sec (floor next-sec-psec trillion)))
+    (setq next-sec-psec (mod next-sec-psec trillion))
+    (list (floor next-sec 65536)
+         (floor (mod next-sec 65536))
+         (floor next-sec-psec 1000000)
+         (floor (mod next-sec-psec 1000000)))))
+
+(defun timer-relative-time (time secs &optional usecs psecs)
+  "Advance TIME by SECS seconds and optionally USECS nanoseconds
+and PSECS picoseconds.  SECS may be either an integer or a
+floating point number."
   (let ((delta (if (floatp secs)
                   (seconds-to-time secs)
                 (list (floor secs 65536) (mod secs 65536)))))
-    (if usecs
-       (setq delta (time-add delta (list 0 0 usecs))))
+    (if (or usecs psecs)
+       (setq delta (time-add delta (list 0 0 (or usecs 0) (or psecs 0)))))
     (time-add time delta)))
 
 (defun timer--time-less-p (t1 t2)
   "Say whether time value T1 is less than time value T2."
   (time-less-p (timer--time t1) (timer--time t2)))
 
-(defun timer-inc-time (timer secs &optional usecs)
-  "Increment the time set in TIMER by SECS seconds and USECS microseconds.
-SECS may be a fraction.  If USECS is omitted, that means it is zero."
+(defun timer-inc-time (timer secs &optional usecs psecs)
+  "Increment the time set in TIMER by SECS seconds, USECS nanoseconds,
+and PSECS picoseconds.  SECS may be a fraction.  If USECS or PSECS are
+omitted, they are treated as zero."
   (setf (timer--time timer)
-        (timer-relative-time (timer--time timer) secs usecs)))
+        (timer-relative-time (timer--time timer) secs usecs psecs)))
 
 (defun timer-set-time-with-usecs (timer time usecs &optional delta)
   "Set the trigger time of TIMER to TIME plus USECS.
@@ -135,6 +148,7 @@ If optional fourth argument DELTA is a positive number, make the timer
 fire repeatedly that many seconds apart."
   (setf (timer--time timer) time)
   (setf (timer--usecs timer) usecs)
+  (setf (timer--psecs timer) 0)
   (setf (timer--repeat-delay timer) (and (numberp delta) (> delta 0) delta))
   timer)
 (make-obsolete 'timer-set-time-with-usecs
@@ -154,6 +168,7 @@ fire repeatedly that many seconds apart."
           (integerp (timer--high-seconds timer))
           (integerp (timer--low-seconds timer))
           (integerp (timer--usecs timer))
+          (integerp (timer--psecs timer))
           (timer--function timer))
       (let ((timers (if idle timer-idle-list timer-list))
            last)
@@ -386,7 +401,7 @@ This function is for compatibility; see also `run-with-timer'."
   "Perform an action the next time Emacs is idle for SECS seconds.
 The action is to call FUNCTION with arguments ARGS.
 SECS may be an integer, a floating point number, or the internal
-time format (HIGH LOW USECS) returned by, e.g., `current-idle-time'.
+time format returned by, e.g., `current-idle-time'.
 If Emacs is currently idle, and has been idle for N seconds (N < SECS),
 then it will call FUNCTION in SECS - N seconds from now.
 
index 930f7d99f9ebee885d836830ac4c7c02d36c3bd4..78afcac9f502e44d23ce50ab763dd82e1ea62df0 100644 (file)
@@ -1170,14 +1170,16 @@ Return nil otherwise."
 (defun proced-time-lessp (t1 t2)
   "Return t if time value T1 is less than time value T2.
 Return `equal' if T1 equals T2.  Return nil otherwise."
-  (with-decoded-time-value ((high1 low1 micro1 t1)
-                           (high2 low2 micro2 t2))
+  (with-decoded-time-value ((high1 low1 micro1 pico1 type1 t1)
+                           (high2 low2 micro2 pico2 type2 t2))
     (cond ((< high1 high2))
           ((< high2 high1) nil)
           ((< low1 low2))
           ((< low2 low1) nil)
           ((< micro1 micro2))
           ((< micro2 micro1) nil)
+         ((< pico1 pico2))
+         ((< pico2 pico1) nil)
           (t 'equal))))
 
 ;;; Sorting
index 37067031da59943078b825ab68fb162326875b5a..17ece1cfe3544f0a1c3b0c148cd40c69592c72a3 100644 (file)
@@ -41,12 +41,14 @@ AC_DEFUN([gl_EARLY],
   # Code from module alloca-opt:
   # Code from module allocator:
   # Code from module careadlinkat:
+  # Code from module clock-time:
   # Code from module crypto/md5:
   # Code from module crypto/sha1:
   # Code from module crypto/sha256:
   # Code from module crypto/sha512:
   # Code from module dosname:
   # Code from module dtoastr:
+  # Code from module dtotimespec:
   # Code from module dup2:
   # Code from module extensions:
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
@@ -55,6 +57,8 @@ AC_DEFUN([gl_EARLY],
   # Code from module getopt-gnu:
   # Code from module getopt-posix:
   # Code from module gettext-h:
+  # Code from module gettime:
+  # Code from module gettimeofday:
   # Code from module ignore-value:
   # Code from module include_next:
   # Code from module intprops:
@@ -67,10 +71,10 @@ AC_DEFUN([gl_EARLY],
   # Code from module multiarch:
   # Code from module nocrash:
   # Code from module pathmax:
+  # Code from module pselect:
   # Code from module pthread_sigmask:
   # Code from module readlink:
   # Code from module signal-h:
-  # Code from module sigprocmask:
   # Code from module snippet/_Noreturn:
   # Code from module snippet/arg-nonnull:
   # Code from module snippet/c++defs:
@@ -78,6 +82,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module socklen:
   # Code from module ssize_t:
   # Code from module stat:
+  # Code from module stat-time:
   # Code from module stdalign:
   # Code from module stdarg:
   dnl Some compilers (e.g., AIX 5.3 cc) need to be in c99 mode
@@ -96,12 +101,17 @@ AC_DEFUN([gl_EARLY],
   # Code from module strtoull:
   # Code from module strtoumax:
   # Code from module symlink:
+  # Code from module sys_select:
   # Code from module sys_stat:
-  # Code from module sys_types:
+  # Code from module sys_time:
   # Code from module time:
   # Code from module time_r:
+  # Code from module timespec:
+  # Code from module timespec-add:
+  # Code from module timespec-sub:
   # Code from module u64:
   # Code from module unistd:
+  # Code from module utimens:
   # Code from module verify:
   # Code from module warnings:
 ])
@@ -124,6 +134,7 @@ AC_DEFUN([gl_INIT],
   gl_source_base='lib'
 gl_FUNC_ALLOCA
 AC_CHECK_FUNCS_ONCE([readlinkat])
+gl_CLOCK_TIME
 gl_MD5
 gl_SHA1
 gl_SHA256
@@ -161,6 +172,13 @@ if test $REPLACE_GETOPT = 1; then
   GNULIB_GL_UNISTD_H_GETOPT=1
 fi
 AC_SUBST([GNULIB_GL_UNISTD_H_GETOPT])
+gl_GETTIME
+gl_FUNC_GETTIMEOFDAY
+if test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1; then
+  AC_LIBOBJ([gettimeofday])
+  gl_PREREQ_GETTIMEOFDAY
+fi
+gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
 AC_REQUIRE([AC_C_INLINE])
 gl_INTTYPES_INCOMPLETE
 AC_REQUIRE([gl_LARGEFILE])
@@ -177,6 +195,11 @@ if test $REPLACE_MKTIME = 1; then
 fi
 gl_TIME_MODULE_INDICATOR([mktime])
 gl_MULTIARCH
+gl_FUNC_PSELECT
+if test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1; then
+  AC_LIBOBJ([pselect])
+fi
+gl_SYS_SELECT_MODULE_INDICATOR([pselect])
 gl_FUNC_PTHREAD_SIGMASK
 if test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1; then
   AC_LIBOBJ([pthread_sigmask])
@@ -192,6 +215,8 @@ gl_UNISTD_MODULE_INDICATOR([readlink])
 gl_SIGNAL_H
 gl_TYPE_SOCKLEN_T
 gt_TYPE_SSIZE_T
+gl_STAT_TIME
+gl_STAT_BIRTHTIME
 gl_STDALIGN_H
 gl_STDARG_H
 AM_STDBOOL_H
@@ -217,9 +242,11 @@ if test $HAVE_SYMLINK = 0 || test $REPLACE_SYMLINK = 1; then
   AC_LIBOBJ([symlink])
 fi
 gl_UNISTD_MODULE_INDICATOR([symlink])
+gl_HEADER_SYS_SELECT
+AC_PROG_MKDIR_P
 gl_HEADER_SYS_STAT_H
 AC_PROG_MKDIR_P
-gl_SYS_TYPES_H
+gl_HEADER_SYS_TIME_H
 AC_PROG_MKDIR_P
 gl_HEADER_TIME_H
 gl_TIME_R
@@ -228,12 +255,13 @@ if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
   gl_PREREQ_TIME_R
 fi
 gl_TIME_MODULE_INDICATOR([time_r])
+gl_TIMESPEC
 AC_REQUIRE([AC_C_INLINE])
 gl_UNISTD_H
+gl_UTIMENS
   gl_gnulib_enabled_dosname=false
   gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
   gl_gnulib_enabled_pathmax=false
-  gl_gnulib_enabled_sigprocmask=false
   gl_gnulib_enabled_stat=false
   gl_gnulib_enabled_strtoll=false
   gl_gnulib_enabled_strtoull=false
@@ -259,18 +287,6 @@ gl_PATHMAX
       gl_gnulib_enabled_pathmax=true
     fi
   }
-  func_gl_gnulib_m4code_sigprocmask ()
-  {
-    if ! $gl_gnulib_enabled_sigprocmask; then
-gl_SIGNALBLOCKING
-if test $HAVE_POSIX_SIGNALBLOCKING = 0; then
-  AC_LIBOBJ([sigprocmask])
-  gl_PREREQ_SIGPROCMASK
-fi
-gl_SIGNAL_MODULE_INDICATOR([sigprocmask])
-      gl_gnulib_enabled_sigprocmask=true
-    fi
-  }
   func_gl_gnulib_m4code_stat ()
   {
     if ! $gl_gnulib_enabled_stat; then
@@ -331,9 +347,6 @@ gl_STDLIB_MODULE_INDICATOR([strtoull])
   if test $REPLACE_LSTAT = 1; then
     func_gl_gnulib_m4code_stat
   fi
-  if test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1; then
-    func_gl_gnulib_m4code_sigprocmask
-  fi
   if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
     func_gl_gnulib_m4code_stat
   fi
@@ -353,7 +366,6 @@ gl_STDLIB_MODULE_INDICATOR([strtoull])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_dosname], [$gl_gnulib_enabled_dosname])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_pathmax], [$gl_gnulib_enabled_pathmax])
-  AM_CONDITIONAL([gl_GNULIB_ENABLED_sigprocmask], [$gl_gnulib_enabled_sigprocmask])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull])
@@ -510,6 +522,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/careadlinkat.h
   lib/dosname.h
   lib/dtoastr.c
+  lib/dtotimespec.c
   lib/dup2.c
   lib/filemode.c
   lib/filemode.h
@@ -521,6 +534,8 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/getopt1.c
   lib/getopt_int.h
   lib/gettext.h
+  lib/gettime.c
+  lib/gettimeofday.c
   lib/ignore-value.h
   lib/intprops.h
   lib/inttypes.in.h
@@ -530,6 +545,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/mktime-internal.h
   lib/mktime.c
   lib/pathmax.h
+  lib/pselect.c
   lib/pthread_sigmask.c
   lib/readlink.c
   lib/sha1.c
@@ -539,7 +555,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/sha512.c
   lib/sha512.h
   lib/signal.in.h
-  lib/sigprocmask.c
+  lib/stat-time.h
   lib/stat.c
   lib/stdalign.in.h
   lib/stdarg.in.h
@@ -557,21 +573,30 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/strtoull.c
   lib/strtoumax.c
   lib/symlink.c
+  lib/sys_select.in.h
   lib/sys_stat.in.h
-  lib/sys_types.in.h
+  lib/sys_time.in.h
   lib/time.in.h
   lib/time_r.c
+  lib/timespec-add.c
+  lib/timespec-sub.c
+  lib/timespec.h
   lib/u64.h
   lib/unistd.in.h
+  lib/utimens.c
+  lib/utimens.h
   lib/verify.h
   m4/00gnulib.m4
   m4/alloca.m4
   m4/c-strtod.m4
+  m4/clock_time.m4
   m4/dup2.m4
   m4/extensions.m4
   m4/filemode.m4
   m4/getloadavg.m4
   m4/getopt.m4
+  m4/gettime.m4
+  m4/gettimeofday.m4
   m4/gnulib-common.m4
   m4/include_next.m4
   m4/inttypes.m4
@@ -585,16 +610,17 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/nocrash.m4
   m4/off_t.m4
   m4/pathmax.m4
+  m4/pselect.m4
   m4/pthread_sigmask.m4
   m4/readlink.m4
   m4/sha1.m4
   m4/sha256.m4
   m4/sha512.m4
   m4/signal_h.m4
-  m4/signalblocking.m4
   m4/socklen.m4
   m4/ssize_t.m4
   m4/st_dm_mode.m4
+  m4/stat-time.m4
   m4/stat.m4
   m4/stdalign.m4
   m4/stdarg.m4
@@ -609,12 +635,18 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/strtoull.m4
   m4/strtoumax.m4
   m4/symlink.m4
+  m4/sys_select_h.m4
+  m4/sys_socket_h.m4
   m4/sys_stat_h.m4
-  m4/sys_types_h.m4
+  m4/sys_time_h.m4
   m4/time_h.m4
   m4/time_r.m4
+  m4/timespec.m4
   m4/tm_gmtoff.m4
   m4/unistd_h.m4
+  m4/utimbuf.m4
+  m4/utimens.m4
+  m4/utimes.m4
   m4/warn-on-use.m4
   m4/warnings.m4
   m4/wchar_t.m4
index a5e10fe94735440103a586b43f03f7253562c505..65424205f3474d0c3f329726e9c138f38a7137be 100644 (file)
@@ -1,3 +1,172 @@
+2012-06-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Support higher-resolution time stamps (Bug#9000).
+       The time stamps are only nanosecond-resolution at the C level,
+       since that's the best that any real-world system supports now.
+       But they are picosecond-resolution at the Lisp level, as that's
+       easy, and leaves room for future OS improvements.
+
+       * Makefile.in (LIB_CLOCK_GETTIME): New macro.
+       (LIBES): Use it.
+
+       * alloc.c (Fgarbage_collect): Port to higher-res time stamps.
+       Don't get current time unless it's needed.
+
+       * atimer.c: Include <sys/time.h> unconditionally, since gnulib
+       now provides it if it's absent.
+       (start_atimer): Port to higher-res time stamps.
+       Check for time stamp overflow.  Don't get current time more
+       often than is needed.
+
+       * buffer.h (struct buffer): Buffer modtime now has high resolution.
+       Include systime.h, not time.h.
+       (NONEXISTENT_MODTIME_NSECS, UNKNOWN_MODTIME_NSECS): New macros.
+
+       * dired.c: Include stat-time.h.
+       (Ffile-attributes): File times now have higher resolution.
+
+       * dispextern.h [HAVE_WINDOW_SYSTEM]: Include systime.h.
+       (struct image): Timestamp now has higher resolution.
+
+       * dispnew.c (PERIODIC_PREEMPTION_CHECKING): Remove, as Emacs always
+       has at least microseconds now.  All uses removed.
+       (update_frame, update_single_window, update_window, update_frame_1)
+       (Fsleep_for, sit_for): Port to higher-resolution time stamps.
+
+       * editfns.c (time_overflow): Now extern.
+       (Fcurrent_time, Fget_internal_run_time, make_time, lisp_time_argument)
+       (float-time, Fformat_time_string, Fcurrent_time_string)
+       (Fcurrent_time_zone): Accept and generate higher-resolution
+       time stamps.
+       (make_time_tail, make_lisp_time, dissassemble_lisp_time)
+       (decode_time_components, lisp_seconds_argument): New functions.
+       (make_time): Now static.
+       (lisp_time_argument): Now returns EMACS_TIME.  New arg ppsec.
+       Report an error if the time is invalid, rather than having the caller
+       do that.
+
+       * fileio.c: Include <stat-time.h>
+       (Fcopy_file): Copy higher-resolution time stamps.
+       Prefer to set the time stamp via a file descriptor if that works.
+       (Fset_file_times, Finsert_file_contents, Fwrite_region)
+       (Fverify_visited_file_modtime, Fclear_visited_file_modtime)
+       (Fvisited_file_modtime, Fset_visited_file_modtime):
+       Support higher-resolution time stamps.
+
+       * fns.c (Frandom): Use nanoseconds, not microseconds, for seed.
+
+       * gtkutil.c (xg_maybe_add_timer): Port to higher-res time stamps.
+
+       * image.c (prepare_image_for_display, clear_image_cache)
+       (lookup_image): Port to higer-resolution time stamps.
+
+       * keyboard.c (start_polling, bind_polling_period):
+       Check for time stamp overflow.
+       (read_char, kbd_buffer_get_event, timer_start_idle)
+       (timer_stop_idle, timer_resume_idle, timer_check_2, timer_check)
+       (Fcurrent_idle_time, init_keyboard, set_waiting_for_input):
+       Port to higher-resolution time stamps.  Do not assume time_t is signed.
+       (decode_timer): New function.  Timers are now vectors of length 9,
+       not 8, to accommodate the picosecond component.
+       (timer_check_2): Use it.
+
+       * nsterm.m (select_timeout, timeval_subtract): Remove.
+       (ns_timeout): Use Emacs's facilities for time stamp arithmetic,
+       as they're a bit more accurate and handle overflow better.
+       (ns_select): Change prototype to be compatible with pselect.
+       (ns_select, ns_term_shutdown): Port to ns-resolution time stamps.
+       * nsterm.h (ns_select): Adjust prototype.
+
+       * msdos.c (EMACS_TIME_ZERO_OR_NEG_P): Remove, as it assumes
+       us-resolution time stamps.
+       (sys_select): Use the new EMACS_TIME_SIGN macro instead.
+
+       * lread.c (read_filtered_event): Port to ns-resolution time stamps.
+
+       * lisp.h (time_overflow): New decl.
+       (wait_reading_process_output): First arg is now intmax_t, not int,
+       to accommodate larger waits.
+
+       * process.h (struct Lisp_Process.read_output_delay):
+       Now counts nanoseconds, not microseconds.
+       * process.c (ADAPTIVE_READ_BUFFERING): Don't worry about
+       EMACS_HAS_USECS.
+       (READ_OUTPUT_DELAY_INCREMENT, Faccept_process_output)
+       (wait_reading_process_output):
+       Port to ns-resolution time stamps.
+       (Faccept_process_output, wait_reading_process_output):
+       Check for time stamp overflow.  Do not assume time_t is signed.
+       (select_wrapper): Remove; we now use pselect.
+       (Fprocess_attributes): Now generates ns-resolution time stamps.
+
+       * sysdep.c: Include utimens.h.  Don't include utime.h
+       or worry about struct utimbuf; gnulib does that for us now.
+       (gettimeofday): Remove; gnulib provides a substitute.
+       (make_timeval): New function.
+       (set_file_times): Now sets ns-resolution time stamps.
+       New arg FD; all uses changed.
+       (time_from_jiffies, ltime_from_jiffies, get_up_time)
+       (system_process_attributes):
+       Now returns ns-resolution time stamp.  All uses changed.
+       Check for time stamp overflow.
+
+       * sysselect.h: Don't depend on HAVE_SYS_SELECT_H; gnulib
+       provides a substitute now.
+
+       * systime.h: Include timespec.h rather than sys/time.h and time.h,
+       since it guarantees struct timespec.
+       (EMACS_TIME): Now struct timespec, so that we can support
+       ns-resolution time stamps.
+       (EMACS_TIME_RESOLUTION, LOG10_EMACS_TIME_RESOLUTION): New macros.
+       (EMACS_HAS_USECS): Remove; Emacs always has sub-second time stamps now.
+       (EMACS_USECS): Remove.
+       (EMACS_SET_USECS): The underlying time stamp now has ns resolution,
+       so multiply the arg by 1000 before storing it.
+       (EMACS_NSECS, EMACS_SECS_ADDR, EMACS_SET_NSECS, EMACS_SET_SECS_NSECS):
+       New macros.
+       (EMACS_GET_TIME, EMACS_ADD_TIME, EMACS_SUB_TIME):
+       Port to ns-resolution time stamps.
+       (EMACS_TIME_NEG_P): Remove; replaced by....
+       (EMACS_TIME_SIGN): New macro.
+       (EMACS_SET_INVALID_TIME, EMACS_TIME_VALID_P)
+       (EMACS_TIME_FROM_DOUBLE, EMACS_TIME_TO_DOUBLE): New macros.
+       (set_file_times, make_time, lisp_time_argument): Adjust signature.
+       (make_timeval, make_lisp_time, decode_time_components): New decls.
+       (EMACS_TIME_CMP): Remove; no longer used.  Plus, it was buggy, in
+       that it mishandled time_t overflow.  You can't compare by subtracting!
+       (EMACS_TIME_EQ, EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE)
+       (EMACS_TIME_LT, EMACS_TIME_LE): Rewrite in terms of timespec_cmp.
+
+       * term.c: Include <sys/time.h>.
+       (timeval_to_Time): New function, for proper overflow wraparound.
+       (term_mouse_position, term_mouse_click): Use it.
+
+       * undo.c (record_first_change): Support higher-resolution time stamps
+       in the undo buffer.
+       (Fprimitive_undo): Use them when restoring time stamps.
+
+       * w32.c (ltime, U64_TO_LISP_TIME, process_times, emacs_gnutls_pull)
+       (w32_get_internal_run_time):
+       Port to higher-resolution Emacs time stamps.
+       (ltime): Now accepts single 64-bit integer, as that's more convenient
+       for callers.
+
+       * xdisp.c (start_hourglass): Port to ns-resolution time stamps.
+
+       * xgselect.c, xgselect.h (xg_select): Add sigmask argument,
+       for compatibility with pselect.  Support ns-resolution time stamps.
+
+       * xmenu.c (x_menu_wait_for_event): Support ns-resolution time stamps.
+
+       * xselect.c (wait_for_property_change, x_get_foreign_selection):
+       Check for time stamp overflow, and support ns-resolution time stamps.
+
+       * xterm.c: Don't include sys/time.h; gnulib does that for us now.
+       Don't worry about whether HAVE_TIMEVAL and HAVE_SELECT are set.
+       (timeval_subtract): Remove; no longer needed.
+       (XTflash, XTring_bell, x_wait_for_event):
+       Port to ns-resolution time stamps.  Don't assume time_t is signed.
+
 2012-06-22  Chong Yidong  <cyd@gnu.org>
 
        * xdisp.c (x_consider_frame_title): Revert last change.
index 47c7d5cfbc210cc3e7d745a8dda49e2ea30ce5ca..40cfe94c707c77a6b772f928d1545877697420f5 100644 (file)
@@ -153,6 +153,8 @@ LIBOTF_LIBS = @LIBOTF_LIBS@
 M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
 M17N_FLT_LIBS = @M17N_FLT_LIBS@
 
+LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
+
 DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_LIBS = @DBUS_LIBS@
 ## dbusbind.o if HAVE_DBUS, else empty.
@@ -384,7 +386,7 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
 ## duplicated symbols.  If the standard libraries were compiled
 ## with GCC, we might need LIB_GCC again after them.
 LIBES = $(LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \
-   $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(DBUS_LIBS) \
+   $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) $(DBUS_LIBS) \
    $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
    $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
    $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
index aba76386dd6d3b282cae9fb983c9c4f79bf8fdb9..490632f282f8c720e7460963d42846e76532c2f5 100644 (file)
@@ -5669,12 +5669,14 @@ See Info node `(elisp)Garbage Collection'.  */)
     }
 
   /* Accumulate statistics.  */
-  EMACS_GET_TIME (t2);
-  EMACS_SUB_TIME (t3, t2, t1);
   if (FLOATP (Vgc_elapsed))
-    Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) +
-                             EMACS_SECS (t3) +
-                             EMACS_USECS (t3) * 1.0e-6);
+    {
+      EMACS_GET_TIME (t2);
+      EMACS_SUB_TIME (t3, t2, t1);
+      Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed)
+                               + EMACS_TIME_TO_DOUBLE (t3));
+    }
+
   gcs_done++;
 
   return Flist (sizeof total / sizeof *total, total);
index 48f22fe0e3e4ca82c3d71d6e0680c2959184d364..e72bc305753c2403eec4b76870ef321909aa9b65 100644 (file)
@@ -26,10 +26,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "blockinput.h"
 #include "atimer.h"
 #include <unistd.h>
-
-#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
-#endif
 
 /* Free-list of atimer structures.  */
 
@@ -94,7 +91,8 @@ start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn,
   /* Round TIME up to the next full second if we don't have
      itimers.  */
 #ifndef HAVE_SETITIMER
-  if (EMACS_USECS (timestamp) != 0)
+  if (EMACS_NSECS (timestamp) != 0
+      && EMACS_SECS (timestamp) < TYPE_MAXIMUM (time_t))
     {
       EMACS_SET_USECS (timestamp, 0);
       EMACS_SET_SECS (timestamp, EMACS_SECS (timestamp) + 1);
@@ -294,18 +292,21 @@ set_alarm (void)
 
       /* Determine s/us till the next timer is ripe.  */
       EMACS_GET_TIME (now);
-      EMACS_SUB_TIME (timestamp, atimers->expiration, now);
 
-#ifdef HAVE_SETITIMER
       /* Don't set the interval to 0; this disables the timer.  */
       if (EMACS_TIME_LE (atimers->expiration, now))
        {
          EMACS_SET_SECS (timestamp, 0);
          EMACS_SET_USECS (timestamp, 1000);
        }
+      else
+       EMACS_SUB_TIME (timestamp, atimers->expiration, now);
+
+
+#ifdef HAVE_SETITIMER
 
       memset (&it, 0, sizeof it);
-      it.it_value = timestamp;
+      it.it_value = make_timeval (timestamp);
       setitimer (ITIMER_REAL, &it, 0);
 #else /* not HAVE_SETITIMER */
       alarm (max (EMACS_SECS (timestamp), 1));
@@ -341,11 +342,10 @@ run_timers (void)
 {
   EMACS_TIME now;
 
-  EMACS_GET_TIME (now);
-
   while (atimers
         && (pending_atimers = interrupt_input_blocked) == 0
-        && EMACS_TIME_LE (atimers->expiration, now))
+        && (EMACS_GET_TIME (now),
+            EMACS_TIME_LE (atimers->expiration, now)))
     {
       struct atimer *t;
 
@@ -363,8 +363,6 @@ run_timers (void)
          t->next = free_atimers;
          free_atimers = t;
        }
-
-      EMACS_GET_TIME (now);
     }
 
   if (! atimers)
index e501c9b73cc1ebc1074c12bfd7bf7015ac19e147..89a4e26fb73dc30e7f77ac9b2d2b3b2f4e2bdc40 100644 (file)
@@ -709,7 +709,7 @@ reset_buffer (register struct buffer *b)
   BVAR (b, filename) = Qnil;
   BVAR (b, file_truename) = Qnil;
   BVAR (b, directory) = (current_buffer) ? BVAR (current_buffer, directory) : Qnil;
-  b->modtime = 0;
+  EMACS_SET_SECS_NSECS (b->modtime, 0, UNKNOWN_MODTIME_NSECS);
   b->modtime_size = -1;
   XSETFASTINT (BVAR (b, save_length), 0);
   b->last_window_start = 1;
@@ -5834,9 +5834,9 @@ An entry (TEXT . POSITION) represents the deletion of the string TEXT
 from (abs POSITION).  If POSITION is positive, point was at the front
 of the text being deleted; if negative, point was at the end.
 
-An entry (t HIGH . LOW) indicates that the buffer previously had
-\"unmodified\" status.  HIGH and LOW are the high and low 16-bit portions
-of the visited file's modification time, as of that time.  If the
+An entry (t HIGH LOW USEC PSEC) indicates that the buffer was previously
+unmodified; (HIGH LOW USEC PSEC) is in the same style as (current-time)
+and is the visited file's modification time, as of that time.  If the
 modification time of the most recent save is different, this entry is
 obsolete.
 
index 8e0604e90c277a3311a8161e075136824e51f399..97b45e15387b035cdaeccdaf2793ff450924c090 100644 (file)
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <sys/types.h> /* for off_t, time_t */
+#include "systime.h" /* for EMACS_TIME */
 
 /* Accessing the parameters of the current buffer.  */
 
@@ -529,10 +530,13 @@ struct buffer
   char local_flags[MAX_PER_BUFFER_VARS];
 
   /* Set to the modtime of the visited file when read or written.
-     -1 means visited file was nonexistent.
-     0 means visited file modtime unknown; in no case complain
-     about any mismatch on next save attempt.  */
-  time_t modtime;
+     EMACS_NSECS (modtime) == NONEXISTENT_MODTIME_NSECS means
+     visited file was nonexistent.  EMACS_NSECS (modtime) ==
+     UNKNOWN_MODTIME_NSECS means visited file modtime unknown;
+     in no case complain about any mismatch on next save attempt.  */
+#define NONEXISTENT_MODTIME_NSECS (-1)
+#define UNKNOWN_MODTIME_NSECS (-2)
+  EMACS_TIME modtime;
   /* Size of the file when modtime was set.  This is used to detect the
      case where the file grew while we were reading it, so the modtime
      is still the same (since it's rounded up to seconds) but we're actually
index 1ce236d567497c5296da9c43064309ff8e18bfa0..b319072aa3344f406b60c1d25e127ad183f50b1b 100644 (file)
@@ -62,6 +62,7 @@ extern struct direct *readdir (DIR *);
 #endif /* HAVE_DIRENT_H */
 
 #include <filemode.h>
+#include <stat-time.h>
 
 #ifdef MSDOS
 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
@@ -893,8 +894,8 @@ Elements of the attribute list are:
  2. File uid as a string or a number.  If a string value cannot be
   looked up, a numeric value, either an integer or a float, is returned.
  3. File gid, likewise.
- 4. Last access time, as a list of two integers.
-  First integer has high-order 16 bits of time, second has low 16 bits.
+ 4. Last access time, as a list of integers (HIGH LOW USEC PSEC) in the
+  same style as (current-time).
   (See a note below about access time on FAT-based filesystems.)
  5. Last modification time, likewise.  This is the time of the last
   change to the file's contents.
@@ -979,9 +980,9 @@ so last access time will always be midnight of that day.  */)
   else
     values[3] = make_fixnum_or_float (s.st_gid);
 
-  values[4] = make_time (s.st_atime);
-  values[5] = make_time (s.st_mtime);
-  values[6] = make_time (s.st_ctime);
+  values[4] = make_lisp_time (get_stat_atime (&s));
+  values[5] = make_lisp_time (get_stat_mtime (&s));
+  values[6] = make_lisp_time (get_stat_ctime (&s));
 
   /* If the file size is a 4-byte type, assume that files of sizes in
      the 2-4 GiB range wrap around to negative values, as this is a
index fc7bec97f7a786cb206427e4889420091cda99ef..63c23b8962fdf45a21ef83b225c822953fee404b 100644 (file)
@@ -68,6 +68,10 @@ typedef Pixmap XImagePtr;
 typedef XImagePtr XImagePtr_or_DC;
 #endif
 
+#ifdef HAVE_WINDOW_SYSTEM
+# include "systime.h"
+#endif
+
 #ifndef HAVE_WINDOW_SYSTEM
 typedef int Cursor;
 #define No_Cursor (0)
@@ -2780,7 +2784,7 @@ struct image
 {
   /* The time in seconds at which the image was last displayed.  Set
      in prepare_image_for_display.  */
-  time_t timestamp;
+  EMACS_TIME timestamp;
 
   /* Pixmaps of the image.  */
   Pixmap pixmap, mask;
index ad675f6e098d63a52555cc0ee6e10f859bed1b2a..5582607ff6a45b8e9527078833ae114436889d1b 100644 (file)
@@ -137,24 +137,11 @@ static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
 static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
 
 \f
-/* Define PERIODIC_PREEMPTION_CHECKING to 1, if micro-second timers
-   are supported, so we can check for input during redisplay at
-   regular intervals.  */
-#ifdef EMACS_HAS_USECS
-#define PERIODIC_PREEMPTION_CHECKING 1
-#else
-#define PERIODIC_PREEMPTION_CHECKING 0
-#endif
-
-#if PERIODIC_PREEMPTION_CHECKING
-
 /* Redisplay preemption timers.  */
 
 static EMACS_TIME preemption_period;
 static EMACS_TIME preemption_next_check;
 
-#endif
-
 /* Nonzero upon entry to redisplay means do not assume anything about
    current contents of actual terminal frame; clear and redraw it.  */
 
@@ -3221,14 +3208,12 @@ update_frame (struct frame *f, int force_p, int inhibit_hairy_id_p)
 
   if (redisplay_dont_pause)
     force_p = 1;
-#if PERIODIC_PREEMPTION_CHECKING
   else if (NILP (Vredisplay_preemption_period))
     force_p = 1;
   else if (!force_p && NUMBERP (Vredisplay_preemption_period))
     {
       EMACS_TIME tm;
       double p = XFLOATINT (Vredisplay_preemption_period);
-      int sec, usec;
 
       if (detect_input_pending_ignore_squeezables ())
        {
@@ -3236,14 +3221,10 @@ update_frame (struct frame *f, int force_p, int inhibit_hairy_id_p)
          goto do_pause;
        }
 
-      sec = (int) p;
-      usec = (p - sec) * 1000000;
-
       EMACS_GET_TIME (tm);
-      EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+      preemption_period = EMACS_TIME_FROM_DOUBLE (p);
       EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
     }
-#endif
 
   if (FRAME_WINDOW_P (f))
     {
@@ -3327,9 +3308,7 @@ update_frame (struct frame *f, int force_p, int inhibit_hairy_id_p)
 #endif
     }
 
-#if PERIODIC_PREEMPTION_CHECKING
  do_pause:
-#endif
   /* Reset flags indicating that a window should be updated.  */
   set_window_update_flags (root_window, 0);
 
@@ -3382,23 +3361,17 @@ update_single_window (struct window *w, int force_p)
 
       if (redisplay_dont_pause)
        force_p = 1;
-#if PERIODIC_PREEMPTION_CHECKING
       else if (NILP (Vredisplay_preemption_period))
        force_p = 1;
       else if (!force_p && NUMBERP (Vredisplay_preemption_period))
        {
          EMACS_TIME tm;
          double p = XFLOATINT (Vredisplay_preemption_period);
-         int sec, usec;
-
-         sec = (int) p;
-         usec = (p - sec) * 1000000;
 
          EMACS_GET_TIME (tm);
-         EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+         preemption_period = EMACS_TIME_FROM_DOUBLE (p);
          EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
        }
-#endif
 
       /* Update W.  */
       update_begin (f);
@@ -3644,10 +3617,9 @@ update_window (struct window *w, int force_p)
 #if PERIODIC_PREEMPTION_CHECKING
            if (!force_p)
              {
-               EMACS_TIME tm, dif;
+               EMACS_TIME tm;
                EMACS_GET_TIME (tm);
-               EMACS_SUB_TIME (dif, preemption_next_check, tm);
-               if (EMACS_TIME_NEG_P (dif))
+               if (EMACS_TIME_LT (preemption_next_check, tm))
                  {
                    EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
                    if (detect_input_pending_ignore_squeezables ())
@@ -4750,10 +4722,9 @@ update_frame_1 (struct frame *f, int force_p, int inhibit_id_p)
 #if PERIODIC_PREEMPTION_CHECKING
          if (!force_p)
            {
-             EMACS_TIME tm, dif;
+             EMACS_TIME tm;
              EMACS_GET_TIME (tm);
-             EMACS_SUB_TIME (dif, preemption_next_check, tm);
-             if (EMACS_TIME_NEG_P (dif))
+             if (EMACS_TIME_LT (preemption_next_check, tm))
                {
                  EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
                  if (detect_input_pending_ignore_squeezables ())
@@ -5967,48 +5938,14 @@ bitch_at_user (void)
                          Sleeping, Waiting
  ***********************************************************************/
 
-/* Convert a positive value DURATION to a seconds count *PSEC plus a
-   microseconds count *PUSEC, rounding up.  On overflow return the
-   maximal value.  */
-void
-duration_to_sec_usec (double duration, int *psec, int *pusec)
-{
-  int MILLION = 1000000;
-  int sec = INT_MAX, usec = MILLION - 1;
-
-  if (duration < INT_MAX + 1.0)
-    {
-      int s = duration;
-      double usdouble = (duration - s) * MILLION;
-      int usfloor = usdouble;
-      int usceil = usfloor + (usfloor < usdouble);
-
-      if (usceil < MILLION)
-       {
-         sec = s;
-         usec = usceil;
-       }
-      else if (sec < INT_MAX)
-       {
-         sec = s + 1;
-         usec = 0;
-       }
-    }
-
-  *psec = sec;
-  *pusec = usec;
-}
-
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
        doc: /* Pause, without updating display, for SECONDS seconds.
 SECONDS may be a floating-point value, meaning that you can wait for a
 fraction of a second.  Optional second arg MILLISECONDS specifies an
-additional wait period, in milliseconds; this may be useful if your
-Emacs was built without floating point support.
+additional wait period, in milliseconds; this is for backwards compatibility.
 \(Not all operating systems support waiting for a fraction of a second.)  */)
   (Lisp_Object seconds, Lisp_Object milliseconds)
 {
-  int sec, usec;
   double duration = extract_float (seconds);
 
   if (!NILP (milliseconds))
@@ -6017,17 +5954,12 @@ Emacs was built without floating point support.
       duration += XINT (milliseconds) / 1000.0;
     }
 
-  if (! (0 < duration))
-    return Qnil;
-
-  duration_to_sec_usec (duration, &sec, &usec);
-
-#ifndef EMACS_HAS_USECS
-  if (sec == 0 && usec != 0)
-    error ("Millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
-#endif
-
-  wait_reading_process_output (sec, usec, 0, 0, Qnil, NULL, 0);
+  if (0 < duration)
+    {
+      EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (duration);
+      wait_reading_process_output (min (EMACS_SECS (t), INTMAX_MAX),
+                                  EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);
+    }
 
   return Qnil;
 }
@@ -6046,7 +5978,8 @@ Emacs was built without floating point support.
 Lisp_Object
 sit_for (Lisp_Object timeout, int reading, int do_display)
 {
-  int sec, usec;
+  intmax_t sec;
+  int nsec;
 
   swallow_events (do_display);
 
@@ -6057,26 +5990,39 @@ sit_for (Lisp_Object timeout, int reading, int do_display)
   if (do_display >= 2)
     redisplay_preserve_echo_area (2);
 
-  if (EQ (timeout, Qt))
+  if (INTEGERP (timeout))
     {
-      sec = 0;
-      usec = 0;
+      sec = XINT (timeout);
+      if (! (0 < sec))
+       return Qt;
+      nsec = 0;
     }
-  else
+  else if (FLOATP (timeout))
     {
-      double duration = extract_float (timeout);
-
-      if (! (0 < duration))
+      double seconds = XFLOAT_DATA (timeout);
+      if (! (0 < seconds))
        return Qt;
-
-      duration_to_sec_usec (duration, &sec, &usec);
+      else
+       {
+         EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (seconds);
+         sec = min (EMACS_SECS (t), INTMAX_MAX);
+         nsec = EMACS_NSECS (t);
+       }
+    }
+  else if (EQ (timeout, Qt))
+    {
+      sec = 0;
+      nsec = 0;
     }
+  else
+    wrong_type_argument (Qnumberp, timeout);
+
 
 #ifdef SIGIO
   gobble_input (0);
 #endif
 
-  wait_reading_process_output (sec, usec, reading ? -1 : 1, do_display,
+  wait_reading_process_output (sec, nsec, reading ? -1 : 1, do_display,
                               Qnil, NULL, 0);
 
   return detect_input_pending () ? Qnil : Qt;
index 1fb20b07e70a386fd1cba052853c077861467352..63e77004f8bd2976c6e7c18711719060a70e69af 100644 (file)
@@ -73,9 +73,8 @@ extern char **environ;
 extern Lisp_Object w32_get_internal_run_time (void);
 #endif
 
-static void time_overflow (void) NO_RETURN;
-static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object,
-                                      int, time_t *, struct tm *);
+static Lisp_Object format_time_string (char const *, ptrdiff_t, EMACS_TIME,
+                                      int, struct tm *);
 static int tm_diff (struct tm *, struct tm *);
 static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
 
@@ -1378,14 +1377,13 @@ DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
 #endif
 
 /* Report that a time value is out of range for Emacs.  */
-static void
+void
 time_overflow (void)
 {
   error ("Specified time is not representable");
 }
 
-/* Return the upper part of the time T (everything but the bottom 16 bits),
-   making sure that it is representable.  */
+/* Return the upper part of the time T (everything but the bottom 16 bits).  */
 static EMACS_INT
 hi_time (time_t t)
 {
@@ -1413,40 +1411,33 @@ lo_time (time_t t)
 
 DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
        doc: /* Return the current time, as the number of seconds since 1970-01-01 00:00:00.
-The time is returned as a list of three integers.  The first has the
-most significant 16 bits of the seconds, while the second has the
-least significant 16 bits.  The third integer gives the microsecond
-count.
-
-The microsecond count is zero on systems that do not provide
-resolution finer than a second.  */)
+The time is returned as a list of integers (HIGH LOW USEC PSEC).
+HIGH has the most significant bits of the seconds, while LOW has the
+least significant 16 bits.  USEC and PSEC are the microsecond and
+picosecond counts.  */)
   (void)
 {
   EMACS_TIME t;
 
   EMACS_GET_TIME (t);
-  return list3 (make_number (hi_time (EMACS_SECS (t))),
-               make_number (lo_time (EMACS_SECS (t))),
-               make_number (EMACS_USECS (t)));
+  return make_lisp_time (t);
 }
 
 DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
        0, 0, 0,
        doc: /* Return the current run time used by Emacs.
-The time is returned as a list of three integers.  The first has the
-most significant 16 bits of the seconds, while the second has the
-least significant 16 bits.  The third integer gives the microsecond
-count.
+The time is returned as a list (HIGH LOW USEC PSEC), using the same
+style as (current-time).
 
 On systems that can't determine the run time, `get-internal-run-time'
-does the same thing as `current-time'.  The microsecond count is zero
-on systems that do not provide resolution finer than a second.  */)
+does the same thing as `current-time'.  */)
   (void)
 {
 #ifdef HAVE_GETRUSAGE
   struct rusage usage;
   time_t secs;
   int usecs;
+  EMACS_TIME t;
 
   if (getrusage (RUSAGE_SELF, &usage) < 0)
     /* This shouldn't happen.  What action is appropriate?  */
@@ -1460,10 +1451,8 @@ on systems that do not provide resolution finer than a second.  */)
       usecs -= 1000000;
       secs++;
     }
-
-  return list3 (make_number (hi_time (secs)),
-               make_number (lo_time (secs)),
-               make_number (usecs));
+  EMACS_SET_SECS_USECS (t, secs, usecs);
+  return make_lisp_time (t);
 #else /* ! HAVE_GETRUSAGE  */
 #ifdef WINDOWSNT
   return w32_get_internal_run_time ();
@@ -1474,80 +1463,151 @@ on systems that do not provide resolution finer than a second.  */)
 }
 \f
 
-/* Make a Lisp list that represents the time T.  */
-Lisp_Object
+/* Make a Lisp list that represents the time T with fraction TAIL.  */
+static Lisp_Object
+make_time_tail (time_t t, Lisp_Object tail)
+{
+  return Fcons (make_number (hi_time (t)),
+               Fcons (make_number (lo_time (t)), tail));
+}
+
+/* Make a Lisp list that represents the system time T.  */
+static Lisp_Object
 make_time (time_t t)
 {
-  return list2 (make_number (hi_time (t)),
-               make_number (lo_time (t)));
+  return make_time_tail (t, Qnil);
+}
+
+/* Make a Lisp list that represents the Emacs time T.  T may be an
+   invalid time, with a slightly negative tv_nsec value such as
+   UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a
+   correspondingly negative picosecond count.  */
+Lisp_Object
+make_lisp_time (EMACS_TIME t)
+{
+  int ns = EMACS_NSECS (t);
+  return make_time_tail (EMACS_SECS (t),
+                        list2 (make_number (ns / 1000),
+                               make_number (ns % 1000 * 1000)));
 }
 
 /* Decode a Lisp list SPECIFIED_TIME that represents a time.
-   If SPECIFIED_TIME is nil, use the current time.
-   Set *RESULT to seconds since the Epoch.
-   If USEC is not null, set *USEC to the microseconds component.
+   Set *PHIGH, *PLOW, *PUSEC, *PPSEC to its parts; do not check their values.
    Return nonzero if successful.  */
+static int
+disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
+                      Lisp_Object *plow, Lisp_Object *pusec,
+                      Lisp_Object *ppsec)
+{
+  if (CONSP (specified_time))
+    {
+      Lisp_Object low = XCDR (specified_time);
+      Lisp_Object usec = make_number (0);
+      Lisp_Object psec = make_number (0);
+      if (CONSP (low))
+       {
+         Lisp_Object low_tail = XCDR (low);
+         low = XCAR (low);
+         if (CONSP (low_tail))
+           {
+             usec = XCAR (low_tail);
+             low_tail = XCDR (low_tail);
+             if (CONSP (low_tail))
+               psec = XCAR (low_tail);
+           }
+         else if (!NILP (low_tail))
+           usec = low_tail;
+       }
+
+      *phigh = XCAR (specified_time);
+      *plow = low;
+      *pusec = usec;
+      *ppsec = psec;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp
+   list, generate the corresponding EMACS_TIME value *RESULT, and
+   if RESULT_PSEC is not null store into *RESULT_PSEC the
+   (nonnegative) difference in picoseconds between the input time and
+   the returned time.  Return nonzero if successful.  */
 int
-lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec)
+decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
+                       Lisp_Object psec, EMACS_TIME *result, int *result_psec)
 {
+  EMACS_INT hi, lo, us, ps;
+  time_t sec;
+  if (! (INTEGERP (high) && INTEGERP (low)
+        && INTEGERP (usec) && INTEGERP (psec)))
+    return 0;
+  hi = XINT (high);
+  lo = XINT (low);
+  us = XINT (usec);
+  ps = XINT (psec);
+
+  /* Normalize out-of-range lower-order components by carrying
+     each overflow into the next higher-order component.  */
+  us += ps / 1000000 - (ps % 1000000 < 0);
+  lo += us / 1000000 - (us % 1000000 < 0);
+  hi += lo >> 16;
+  ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0);
+  us = us % 1000000 + 1000000 * (us % 1000000 < 0);
+  lo &= (1 << 16) - 1;
+
+  /* Check for overflow in the highest-order component.  */
+  if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi)
+        && hi <= TIME_T_MAX >> 16))
+    return 0;
+
+  sec = hi;
+  EMACS_SET_SECS_NSECS (*result, (sec << 16) + lo, us * 1000 + ps / 1000);
+  if (result_psec)
+    *result_psec = ps % 1000;
+  return 1;
+}
+
+/* Decode a Lisp list SPECIFIED_TIME that represents a time.
+   If SPECIFIED_TIME is nil, use the current time.
+   Round the time down to the nearest EMACS_TIME value, and
+   if PPSEC is not null store into *PPSEC the (nonnegative) difference in
+   picoseconds between the input time and the returned time.
+   Return seconds since the Epoch.
+   Signal an error if unsuccessful.  */
+EMACS_TIME
+lisp_time_argument (Lisp_Object specified_time, int *ppsec)
+{
+  EMACS_TIME t;
   if (NILP (specified_time))
+    EMACS_GET_TIME (t);
+  else
     {
-      if (usec)
-        {
-          EMACS_TIME t;
-
-          EMACS_GET_TIME (t);
-          *usec = EMACS_USECS (t);
-          *result = EMACS_SECS (t);
-          return 1;
-        }
-      else
-        return time (result) != -1;
+      Lisp_Object high, low, usec, psec;
+      if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
+            && decode_time_components (high, low, usec, psec, &t, ppsec)))
+       error ("Invalid time specification");
     }
+  return t;
+}
+
+/* Like lisp_time_argument, except decode only the seconds part,
+   and do not check the subseconds part, and always round down.  */
+static time_t
+lisp_seconds_argument (Lisp_Object specified_time)
+{
+  if (NILP (specified_time))
+    return time (NULL);
   else
     {
-      Lisp_Object high, low;
-      EMACS_INT hi;
-      high = Fcar (specified_time);
-      CHECK_NUMBER (high);
-      low = Fcdr (specified_time);
-      if (CONSP (low))
-        {
-          if (usec)
-            {
-              Lisp_Object usec_l = Fcdr (low);
-              if (CONSP (usec_l))
-                usec_l = Fcar (usec_l);
-              if (NILP (usec_l))
-                *usec = 0;
-              else
-                {
-                  CHECK_NUMBER (usec_l);
-                 if (! (0 <= XINT (usec_l) && XINT (usec_l) < 1000000))
-                   return 0;
-                  *usec = XINT (usec_l);
-                }
-            }
-          low = Fcar (low);
-        }
-      else if (usec)
-        *usec = 0;
-      CHECK_NUMBER (low);
-      hi = XINT (high);
-
-      /* Check for overflow, helping the compiler for common cases
-        where no runtime check is needed, and taking care not to
-        convert negative numbers to unsigned before comparing them.  */
-      if (! ((TYPE_SIGNED (time_t)
-             ? (TIME_T_MIN >> 16 <= MOST_NEGATIVE_FIXNUM
-                || TIME_T_MIN >> 16 <= hi)
-             : 0 <= hi)
-            && (MOST_POSITIVE_FIXNUM <= TIME_T_MAX >> 16
-                || hi <= TIME_T_MAX >> 16)))
-       return 0;
-
-      *result = (hi << 16) + (XINT (low) & 0xffff);
-      return 1;
+      Lisp_Object high, low, usec, psec;
+      EMACS_TIME t;
+      if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
+            && decode_time_components (high, low, make_number (0),
+                                       make_number (0), &t, 0)))
+       error ("Invalid time specification");
+      return EMACS_SECS (t);
     }
 }
 
@@ -1555,22 +1615,22 @@ DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0,
        doc: /* Return the current time, as a float number of seconds since the epoch.
 If SPECIFIED-TIME is given, it is the time to convert to float
 instead of the current time.  The argument should have the form
-(HIGH LOW) or (HIGH LOW USEC). Thus, you can use times obtained from
-`current-time' and from `file-attributes'.  SPECIFIED-TIME can also
-have the form (HIGH . LOW), but this is considered obsolete.
+(HIGH LOW) or (HIGH LOW USEC) or (HIGH LOW USEC PSEC).  Thus,
+you can use times from `current-time' and from `file-attributes'.
+SPECIFIED-TIME can also have the form (HIGH . LOW), but this is
+considered obsolete.
 
 WARNING: Since the result is floating point, it may not be exact.
 If precise time stamps are required, use either `current-time',
 or (if you need time as a string) `format-time-string'.  */)
   (Lisp_Object specified_time)
 {
-  time_t sec;
-  int usec;
-
-  if (! lisp_time_argument (specified_time, &sec, &usec))
-    error ("Invalid time specification");
-
-  return make_float ((sec * 1e6 + usec) / 1e6);
+  int psec;
+  EMACS_TIME t = lisp_time_argument (specified_time, &psec);
+  double ps = (1000 * 1000 * 1000 <= INTMAX_MAX / 1000
+              ? EMACS_NSECS (t) * (intmax_t) 1000 + psec
+              : EMACS_NSECS (t) * 1e3 + psec);
+  return make_float (EMACS_SECS (t) + ps / 1e12);
 }
 
 /* Write information into buffer S of size MAXSIZE, according to the
@@ -1625,7 +1685,7 @@ emacs_nmemftime (char *s, size_t maxsize, const char *format,
 
 DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0,
        doc: /* Use FORMAT-STRING to format the time TIME, or now if omitted.
-TIME is specified as (HIGH LOW . IGNORED), as returned by
+TIME is specified as (HIGH LOW USEC PSEC), as returned by
 `current-time' or `file-attributes'.  The obsolete form (HIGH . LOW)
 is also still accepted.
 The third, optional, argument UNIVERSAL, if non-nil, means describe TIME
@@ -1679,41 +1739,36 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".
 usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL)  */)
   (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
 {
-  time_t t;
+  EMACS_TIME t = lisp_time_argument (timeval, 0);
   struct tm tm;
 
   CHECK_STRING (format_string);
   format_string = code_convert_string_norecord (format_string,
                                                Vlocale_coding_system, 1);
   return format_time_string (SSDATA (format_string), SBYTES (format_string),
-                            timeval, ! NILP (universal), &t, &tm);
+                            t, ! NILP (universal), &tm);
 }
 
 static Lisp_Object
 format_time_string (char const *format, ptrdiff_t formatlen,
-                   Lisp_Object timeval, int ut, time_t *tval, struct tm *tmp)
+                   EMACS_TIME t, int ut, struct tm *tmp)
 {
   char buffer[4000];
   char *buf = buffer;
   ptrdiff_t size = sizeof buffer;
   size_t len;
   Lisp_Object bufstring;
-  int usec;
-  int ns;
+  int ns = EMACS_NSECS (t);
   struct tm *tm;
   USE_SAFE_ALLOCA;
 
-  if (! lisp_time_argument (timeval, tval, &usec))
-    error ("Invalid time specification");
-  ns = usec * 1000;
-
   while (1)
     {
       BLOCK_INPUT;
 
       synchronize_system_time_locale ();
 
-      tm = ut ? gmtime (tval) : localtime (tval);
+      tm = ut ? gmtime (EMACS_SECS_ADDR (t)) : localtime (EMACS_SECS_ADDR (t));
       if (! tm)
        {
          UNBLOCK_INPUT;
@@ -1758,17 +1813,13 @@ east of Greenwich.  (Note that Common Lisp has different meanings for
 DOW and ZONE.)  */)
   (Lisp_Object specified_time)
 {
-  time_t time_spec;
+  time_t time_spec = lisp_seconds_argument (specified_time);
   struct tm save_tm;
   struct tm *decoded_time;
   Lisp_Object list_args[9];
 
-  if (! lisp_time_argument (specified_time, &time_spec, NULL))
-    error ("Invalid time specification");
-
   BLOCK_INPUT;
   decoded_time = localtime (&time_spec);
-  /* Make a copy, in case a signal handler modifies TZ or the struct.  */
   if (decoded_time)
     save_tm = *decoded_time;
   UNBLOCK_INPUT;
@@ -1919,14 +1970,11 @@ Thus, you can use times obtained from `current-time' and from
 but this is considered obsolete.  */)
   (Lisp_Object specified_time)
 {
-  time_t value;
+  time_t value = lisp_seconds_argument (specified_time);
   struct tm *tm;
   char buf[sizeof "Mon Apr 30 12:49:17 " + INT_STRLEN_BOUND (int) + 1];
   int len IF_LINT (= 0);
 
-  if (! lisp_time_argument (specified_time, &value, NULL))
-    error ("Invalid time specification");
-
   /* Convert to a string in ctime format, except without the trailing
      newline, and without the 4-digit year limit.  Don't use asctime
      or ctime, as they might dump core if the year is outside the
@@ -1994,17 +2042,17 @@ in this case, `current-time-zone' returns a list containing nil for
 the data it can't find.  */)
   (Lisp_Object specified_time)
 {
-  time_t value;
+  EMACS_TIME value;
   int offset;
   struct tm *t;
   struct tm localtm;
   Lisp_Object zone_offset, zone_name;
 
   zone_offset = Qnil;
-  zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time,
-                                 0, &value, &localtm);
+  EMACS_SET_SECS_NSECS (value, lisp_seconds_argument (specified_time), 0);
+  zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value, 0, &localtm);
   BLOCK_INPUT;
-  t = gmtime (&value);
+  t = gmtime (EMACS_SECS_ADDR (value));
   if (t)
     offset = tm_diff (&localtm, t);
   UNBLOCK_INPUT;
index 8b69ed5eae402b31d8b77660d980740b598c5e00..824a92148cb01ca5297bbe448e77dc0e33c6f74c 100644 (file)
@@ -76,6 +76,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 
 #include "systime.h"
+#include <stat-time.h>
 
 #ifdef HPUX
 #include <netio.h>
@@ -1931,7 +1932,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
       /* Ensure file is writable while its modified time is set.  */
       attributes = GetFileAttributes (filename);
       SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY);
-      if (set_file_times (filename, now, now))
+      if (set_file_times (-1, filename, now, now))
        {
          /* Restore original attributes.  */
          SetFileAttributes (filename, attributes);
@@ -2054,24 +2055,21 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
     }
 #endif
 
-  /* Closing the output clobbers the file times on some systems.  */
-  if (emacs_close (ofd) < 0)
-    report_file_error ("I/O error", Fcons (newname, Qnil));
-
   if (input_file_statable_p)
     {
       if (!NILP (keep_time))
        {
-         EMACS_TIME atime, mtime;
-         EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
-         EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
-         if (set_file_times (SSDATA (encoded_newname),
-                             atime, mtime))
+         EMACS_TIME atime = get_stat_atime (&st);
+         EMACS_TIME mtime = get_stat_mtime (&st);
+         if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime))
            xsignal2 (Qfile_date_error,
                      build_string ("Cannot set file date"), newname);
        }
     }
 
+  if (emacs_close (ofd) < 0)
+    report_file_error ("I/O error", Fcons (newname, Qnil));
+
   emacs_close (ifd);
 
 #ifdef MSDOS
@@ -3034,11 +3032,7 @@ Use the current time if TIMESTAMP is nil.  TIMESTAMP is in the format of
 {
   Lisp_Object absname, encoded_absname;
   Lisp_Object handler;
-  time_t sec;
-  int usec;
-
-  if (! lisp_time_argument (timestamp, &sec, &usec))
-    error ("Invalid time specification");
+  EMACS_TIME t = lisp_time_argument (timestamp, 0);
 
   absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
 
@@ -3051,12 +3045,7 @@ Use the current time if TIMESTAMP is nil.  TIMESTAMP is in the format of
   encoded_absname = ENCODE_FILE (absname);
 
   {
-    EMACS_TIME t;
-
-    EMACS_SET_SECS (t, sec);
-    EMACS_SET_USECS (t, usec);
-
-    if (set_file_times (SSDATA (encoded_absname), t, t))
+    if (set_file_times (-1, SSDATA (encoded_absname), t, t))
       {
 #ifdef DOS_NT
         struct stat st;
@@ -4205,7 +4194,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (NILP (handler))
        {
-         current_buffer->modtime = st.st_mtime;
+         current_buffer->modtime = get_stat_mtime (&st);
          current_buffer->modtime_size = st.st_size;
          BVAR (current_buffer, filename) = orig_filename;
        }
@@ -4365,7 +4354,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
     }
 
   if (!NILP (visit)
-      && current_buffer->modtime == -1)
+      && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
     {
       /* If visiting nonexistent file, return nil.  */
       errno = save_errno;
@@ -4803,7 +4792,7 @@ This calls `write-region-annotate-functions' at the start, and
      next attempt to save.  */
   if (visiting)
     {
-      current_buffer->modtime = st.st_mtime;
+      current_buffer->modtime = get_stat_mtime (&st);
       current_buffer->modtime_size = st.st_size;
     }
 
@@ -5080,6 +5069,7 @@ See Info node `(elisp)Modification Time' for more details.  */)
   struct stat st;
   Lisp_Object handler;
   Lisp_Object filename;
+  EMACS_TIME mtime, diff, one_second;
 
   if (NILP (buf))
     b = current_buffer;
@@ -5090,7 +5080,7 @@ See Info node `(elisp)Modification Time' for more details.  */)
     }
 
   if (!STRINGP (BVAR (b, filename))) return Qt;
-  if (b->modtime == 0) return Qt;
+  if (EMACS_NSECS (b->modtime) == UNKNOWN_MODTIME_NSECS) return Qt;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -5101,20 +5091,25 @@ See Info node `(elisp)Modification Time' for more details.  */)
 
   filename = ENCODE_FILE (BVAR (b, filename));
 
-  if (stat (SSDATA (filename), &st) < 0)
+  if (stat (SSDATA (filename), &st) == 0)
+    mtime = get_stat_mtime (&st);
+  else
     {
       /* If the file doesn't exist now and didn't exist before,
         we say that it isn't modified, provided the error is a tame one.  */
-      if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
-       st.st_mtime = -1;
-      else
-       st.st_mtime = 0;
+      int ns = (errno == ENOENT || errno == EACCES || errno == ENOTDIR
+               ? NONEXISTENT_MODTIME_NSECS
+               : UNKNOWN_MODTIME_NSECS);
+      EMACS_SET_SECS_NSECS (mtime, 0, ns);
     }
-  if ((st.st_mtime == b->modtime
-       /* If both are positive, accept them if they are off by one second.  */
-       || (st.st_mtime > 0 && b->modtime > 0
-          && (st.st_mtime - 1 == b->modtime
-              || st.st_mtime == b->modtime - 1)))
+  if ((EMACS_TIME_EQ (mtime, b->modtime)
+       /* If both exist, accept them if they are off by one second.  */
+       || (EMACS_TIME_VALID_P (mtime) && EMACS_TIME_VALID_P (b->modtime)
+          && ((EMACS_TIME_LT (mtime, b->modtime)
+               ? EMACS_SUB_TIME (diff, b->modtime, mtime)
+               : EMACS_SUB_TIME (diff, mtime, b->modtime)),
+              EMACS_SET_SECS_NSECS (one_second, 1, 0),
+              EMACS_TIME_LE (diff, one_second))))
       && (st.st_size == b->modtime_size
           || b->modtime_size < 0))
     return Qt;
@@ -5127,7 +5122,7 @@ DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
 Next attempt to save will certainly not complain of a discrepancy.  */)
   (void)
 {
-  current_buffer->modtime = 0;
+  EMACS_SET_SECS_NSECS (current_buffer->modtime, 0, UNKNOWN_MODTIME_NSECS);
   current_buffer->modtime_size = -1;
   return Qnil;
 }
@@ -5135,16 +5130,16 @@ Next attempt to save will certainly not complain of a discrepancy.  */)
 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
        Svisited_file_modtime, 0, 0, 0,
        doc: /* Return the current buffer's recorded visited file modification time.
-The value is a list of the form (HIGH LOW), like the time values that
+The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
 `file-attributes' returns.  If the current buffer has no recorded file
 modification time, this function returns 0.  If the visited file
 doesn't exist, HIGH will be -1.
 See Info node `(elisp)Modification Time' for more details.  */)
   (void)
 {
-  if (! current_buffer->modtime)
+  if (EMACS_NSECS (current_buffer->modtime) < 0)
     return make_number (0);
-  return make_time (current_buffer->modtime);
+  return make_lisp_time (current_buffer->modtime);
 }
 
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@@ -5154,12 +5149,12 @@ Useful if the buffer was not read from the file normally
 or if the file itself has been changed for some known benign reason.
 An argument specifies the modification time value to use
 \(instead of that of the visited file), in the form of a list
-\(HIGH . LOW) or (HIGH LOW).  */)
+\(HIGH LOW USEC PSEC) as returned by `current-time'.  */)
   (Lisp_Object time_list)
 {
   if (!NILP (time_list))
     {
-      CONS_TO_INTEGER (time_list, time_t, current_buffer->modtime);
+      current_buffer->modtime = lisp_time_argument (time_list, 0);
       current_buffer->modtime_size = -1;
     }
   else
@@ -5181,7 +5176,7 @@ An argument specifies the modification time value to use
 
       if (stat (SSDATA (filename), &st) >= 0)
         {
-         current_buffer->modtime = st.st_mtime;
+         current_buffer->modtime = get_stat_mtime (&st);
           current_buffer->modtime_size = st.st_size;
         }
     }
index 676e53ccbd88fdb8bd373ed5d4b4df5c2840bab9..515cd28328b7b5a61d54b0fb62ed04accff7e004 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -80,7 +80,7 @@ Other values of LIMIT are ignored.  */)
     {
       EMACS_TIME t;
       EMACS_GET_TIME (t);
-      seed_random (getpid () ^ EMACS_SECS (t) ^ EMACS_USECS (t));
+      seed_random (getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t));
     }
 
   if (NATNUMP (limit) && XFASTINT (limit) != 0)
index 4cf421b6616683827f7538a911b1cb3e72498266..51c56e49540ac51b16eb802ac6e5a25dcffd3e5e 100644 (file)
@@ -1612,16 +1612,16 @@ xg_maybe_add_timer (gpointer data)
 {
   struct xg_dialog_data *dd = (struct xg_dialog_data *) data;
   EMACS_TIME next_time = timer_check ();
-  long secs = EMACS_SECS (next_time);
-  long usecs = EMACS_USECS (next_time);
 
   dd->timerid = 0;
 
-  if (secs >= 0 && usecs >= 0 && secs < ((guint)-1)/1000)
+  if (EMACS_TIME_VALID_P (next_time))
     {
-      dd->timerid = g_timeout_add (secs * 1000 + usecs/1000,
-                                   xg_maybe_add_timer,
-                                   dd);
+      time_t s = EMACS_SECS (next_time);
+      int per_ms = EMACS_TIME_RESOLUTION / 1000;
+      int ms = (EMACS_NSECS (next_time) + per_ms - 1) / per_ms;
+      if (s <= ((guint) -1 - ms) / 1000)
+       dd->timerid = g_timeout_add (s * 1000 + ms, xg_maybe_add_timer, dd);
     }
   return FALSE;
 }
index 103f0a7feb6b6f38b23b1a21610afd1ab7745804..47b14a333e9579ad0facaf92222af82d932910d0 100644 (file)
@@ -1062,11 +1062,8 @@ check_image_size (struct frame *f, int width, int height)
 void
 prepare_image_for_display (struct frame *f, struct image *img)
 {
-  EMACS_TIME t;
-
   /* We're about to display IMG, so set its timestamp to `now'.  */
-  EMACS_GET_TIME (t);
-  img->timestamp = EMACS_SECS (t);
+  EMACS_GET_TIME (img->timestamp);
 
   /* If IMG doesn't have a pixmap yet, load it now, using the image
      type dependent loader function.  */
@@ -1514,8 +1511,8 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
       else if (INTEGERP (Vimage_cache_eviction_delay))
        {
          /* Free cache based on timestamp.  */
-         EMACS_TIME t;
-         double old, delay;
+         EMACS_TIME old, t;
+         double delay;
          ptrdiff_t nimages = 0;
 
          for (i = 0; i < c->used; ++i)
@@ -1530,12 +1527,12 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
          delay = max (delay, 1);
 
          EMACS_GET_TIME (t);
-         old = EMACS_SECS (t) - delay;
+         EMACS_SUB_TIME (old, t, EMACS_TIME_FROM_DOUBLE (delay));
 
          for (i = 0; i < c->used; ++i)
            {
              struct image *img = c->images[i];
-             if (img && img->timestamp < old)
+             if (img && EMACS_TIME_LT (img->timestamp, old))
                {
                  free_image (f, img);
                  ++nfreed;
@@ -1708,7 +1705,6 @@ lookup_image (struct frame *f, Lisp_Object spec)
 {
   struct image *img;
   EMACS_UINT hash;
-  EMACS_TIME now;
 
   /* F must be a window-system frame, and SPEC must be a valid image
      specification.  */
@@ -1802,8 +1798,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
     }
 
   /* We're using IMG, so set its timestamp to `now'.  */
-  EMACS_GET_TIME (now);
-  img->timestamp = EMACS_SECS (now);
+  EMACS_GET_TIME (img->timestamp);
 
   /* Value is the image id.  */
   return img->id;
index 3e197ab49387a2d9467984815122a41c595b8387..9b80c5c7019d5c725b48ef0c82884d9b7838e07f 100644 (file)
@@ -2020,12 +2020,13 @@ start_polling (void)
       if (poll_timer == NULL
          || EMACS_SECS (poll_timer->interval) != polling_period)
        {
+         time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
          EMACS_TIME interval;
 
          if (poll_timer)
            cancel_atimer (poll_timer);
 
-         EMACS_SET_SECS_USECS (interval, polling_period, 0);
+         EMACS_SET_SECS_USECS (interval, period, 0);
          poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
                                     poll_for_input, NULL);
        }
@@ -2093,7 +2094,7 @@ void
 bind_polling_period (int n)
 {
 #ifdef POLL_FOR_INPUT
-  int new = polling_period;
+  EMACS_INT new = polling_period;
 
   if (n > new)
     new = n;
@@ -2223,7 +2224,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
 /* Input of single characters from keyboard */
 
 static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, int *used_mouse_menu,
-                                        struct timeval *end_time);
+                                        EMACS_TIME *end_time);
 static void record_char (Lisp_Object c);
 
 static Lisp_Object help_form_saved_window_configs;
@@ -2275,7 +2276,7 @@ do { if (polling_stopped_here) start_polling ();  \
 Lisp_Object
 read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
           Lisp_Object prev_event,
-          int *used_mouse_menu, struct timeval *end_time)
+          int *used_mouse_menu, EMACS_TIME *end_time)
 {
   volatile Lisp_Object c;
   ptrdiff_t jmpcount;
@@ -3783,7 +3784,7 @@ clear_event (struct input_event *event)
 static Lisp_Object
 kbd_buffer_get_event (KBOARD **kbp,
                       int *used_mouse_menu,
-                      struct timeval *end_time)
+                      EMACS_TIME *end_time)
 {
   Lisp_Object obj;
 
@@ -3857,8 +3858,9 @@ kbd_buffer_get_event (KBOARD **kbp,
          else
            {
              EMACS_SUB_TIME (duration, *end_time, duration);
-             wait_reading_process_output (EMACS_SECS (duration),
-                                          EMACS_USECS (duration),
+             wait_reading_process_output (min (EMACS_SECS (duration),
+                                               INTMAX_MAX),
+                                          EMACS_NSECS (duration),
                                           -1, 1, Qnil, NULL, 0);
            }
        }
@@ -4253,7 +4255,7 @@ timer_start_idle (void)
   Lisp_Object timers;
 
   /* If we are already in the idle state, do nothing.  */
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     return;
 
   EMACS_GET_TIME (timer_idleness_start_time);
@@ -4267,7 +4269,7 @@ timer_start_idle (void)
 
       timer = XCAR (timers);
 
-      if (!VECTORP (timer) || ASIZE (timer) != 8)
+      if (!VECTORP (timer) || ASIZE (timer) != 9)
        continue;
       ASET (timer, 0, Qnil);
     }
@@ -4278,7 +4280,7 @@ timer_start_idle (void)
 static void
 timer_stop_idle (void)
 {
-  EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
+  EMACS_SET_INVALID_TIME (timer_idleness_start_time);
 }
 
 /* Resume idle timer from last idle start time.  */
@@ -4286,7 +4288,7 @@ timer_stop_idle (void)
 static void
 timer_resume_idle (void)
 {
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     return;
 
   timer_idleness_start_time = timer_last_idleness_start_time;
@@ -4300,6 +4302,24 @@ struct input_event last_timer_event EXTERNALLY_VISIBLE;
    ...).  Each element has the form (FUN . ARGS).  */
 Lisp_Object pending_funcalls;
 
+/* If TIMER is a valid timer, return nonzero and place its value into
+   *RESULT.  Otherwise return zero.  */
+static int
+decode_timer (Lisp_Object timer, EMACS_TIME *result)
+{
+  Lisp_Object *vector;
+
+  if (! (VECTORP (timer) && ASIZE (timer) == 9))
+    return 0;
+  vector = XVECTOR (timer)->contents;
+  if (! NILP (vector[0]))
+    return 0;
+
+  return decode_time_components (vector[1], vector[2], vector[3], vector[4],
+                                result, 0);
+}
+
+
 /* Check whether a timer has fired.  To prevent larger problems we simply
    disregard elements that are not proper timers.  Do not make a circular
    timer list for the time being.
@@ -4317,17 +4337,16 @@ timer_check_2 (void)
 {
   EMACS_TIME nexttime;
   EMACS_TIME now;
-  EMACS_TIME idleness_now IF_LINT (= {0});
+  EMACS_TIME idleness_now;
   Lisp_Object timers, idle_timers, chosen_timer;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
-  EMACS_SET_SECS (nexttime, -1);
-  EMACS_SET_USECS (nexttime, -1);
+  EMACS_SET_INVALID_TIME (nexttime);
 
   /* Always consider the ordinary timers.  */
   timers = Vtimer_list;
   /* Consider the idle timers only if Emacs is idle.  */
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     idle_timers = Vtimer_idle_list;
   else
     idle_timers = Qnil;
@@ -4345,8 +4364,10 @@ timer_check_2 (void)
   if (CONSP (timers) || CONSP (idle_timers))
     {
       EMACS_GET_TIME (now);
-      if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+      if (EMACS_TIME_VALID_P (timer_idleness_start_time))
        EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
+      else
+       EMACS_SET_SECS_NSECS (idleness_now, 0, 0);
     }
 
   while (CONSP (timers) || CONSP (idle_timers))
@@ -4355,113 +4376,84 @@ timer_check_2 (void)
       Lisp_Object timer = Qnil, idle_timer = Qnil;
       EMACS_TIME timer_time, idle_timer_time;
       EMACS_TIME difference;
-      EMACS_TIME timer_difference IF_LINT (= {0});
-      EMACS_TIME idle_timer_difference IF_LINT (= {0});
+      EMACS_TIME timer_difference, idle_timer_difference;
+      int ripe, timer_ripe = 0, idle_timer_ripe = 0;
 
-      /* Skip past invalid timers and timers already handled.  */
+      EMACS_SET_INVALID_TIME (timer_difference);
+      EMACS_SET_INVALID_TIME (idle_timer_difference);
+
+      /* Set TIMER and TIMER_DIFFERENCE
+        based on the next ordinary timer.
+        TIMER_DIFFERENCE is the distance in time from NOW to when
+        this timer becomes ripe (negative if it's already ripe).
+         Skip past invalid timers and timers already handled.  */
       if (CONSP (timers))
        {
          timer = XCAR (timers);
-         if (!VECTORP (timer) || ASIZE (timer) != 8)
+         if (! decode_timer (timer, &timer_time))
            {
              timers = XCDR (timers);
              continue;
            }
-         vector = XVECTOR (timer)->contents;
 
-         if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
-             || !INTEGERP (vector[3])
-             || ! NILP (vector[0]))
-           {
-             timers = XCDR (timers);
-             continue;
-           }
+         timer_ripe = EMACS_TIME_LE (timer_time, now);
+         if (timer_ripe)
+           EMACS_SUB_TIME (timer_difference, now, timer_time);
+         else
+           EMACS_SUB_TIME (timer_difference, timer_time, now);
        }
+
+      /* Likewise for IDLE_TIMER and IDLE_TIMER_DIFFERENCE
+        based on the next idle timer.  */
       if (CONSP (idle_timers))
        {
-         timer = XCAR (idle_timers);
-         if (!VECTORP (timer) || ASIZE (timer) != 8)
-           {
-             idle_timers = XCDR (idle_timers);
-             continue;
-           }
-         vector = XVECTOR (timer)->contents;
-
-         if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
-             || !INTEGERP (vector[3])
-             || ! NILP (vector[0]))
+         idle_timer = XCAR (idle_timers);
+         if (! decode_timer (idle_timer, &idle_timer_time))
            {
              idle_timers = XCDR (idle_timers);
              continue;
            }
-       }
-
-      /* Set TIMER, TIMER_TIME and TIMER_DIFFERENCE
-        based on the next ordinary timer.
-        TIMER_DIFFERENCE is the distance in time from NOW to when
-        this timer becomes ripe (negative if it's already ripe).  */
-      if (CONSP (timers))
-       {
-         timer = XCAR (timers);
-         vector = XVECTOR (timer)->contents;
-         EMACS_SET_SECS (timer_time,
-                         (XINT (vector[1]) << 16) | (XINT (vector[2])));
-         EMACS_SET_USECS (timer_time, XINT (vector[3]));
-         EMACS_SUB_TIME (timer_difference, timer_time, now);
-       }
 
-      /* Set IDLE_TIMER, IDLE_TIMER_TIME and IDLE_TIMER_DIFFERENCE
-        based on the next idle timer.  */
-      if (CONSP (idle_timers))
-       {
-         idle_timer = XCAR (idle_timers);
-         vector = XVECTOR (idle_timer)->contents;
-         EMACS_SET_SECS (idle_timer_time,
-                         (XINT (vector[1]) << 16) | (XINT (vector[2])));
-         EMACS_SET_USECS (idle_timer_time, XINT (vector[3]));
-         EMACS_SUB_TIME (idle_timer_difference, idle_timer_time, idleness_now);
+         idle_timer_ripe = EMACS_TIME_LE (idle_timer_time, idleness_now);
+         if (idle_timer_ripe)
+           EMACS_SUB_TIME (idle_timer_difference,
+                           idleness_now, idle_timer_time);
+         else
+           EMACS_SUB_TIME (idle_timer_difference,
+                           idle_timer_time, idleness_now);
        }
 
       /* Decide which timer is the next timer,
-        and set CHOSEN_TIMER, VECTOR and DIFFERENCE accordingly.
+        and set CHOSEN_TIMER, DIFFERENCE, and RIPE accordingly.
         Also step down the list where we found that timer.  */
 
-      if (CONSP (timers) && CONSP (idle_timers))
-       {
-         EMACS_TIME temp;
-         EMACS_SUB_TIME (temp, timer_difference, idle_timer_difference);
-         if (EMACS_TIME_NEG_P (temp))
-           {
-             chosen_timer = timer;
-             timers = XCDR (timers);
-             difference = timer_difference;
-           }
-         else
-           {
-             chosen_timer = idle_timer;
-             idle_timers = XCDR (idle_timers);
-             difference = idle_timer_difference;
-           }
-       }
-      else if (CONSP (timers))
+      if (EMACS_TIME_VALID_P (timer_difference)
+         && (! EMACS_TIME_VALID_P (idle_timer_difference)
+             || idle_timer_ripe < timer_ripe
+             || (idle_timer_ripe == timer_ripe
+                 && (timer_ripe
+                     ? EMACS_TIME_LT (idle_timer_difference,
+                                      timer_difference)
+                     : EMACS_TIME_LT (timer_difference,
+                                      idle_timer_difference)))))
        {
          chosen_timer = timer;
          timers = XCDR (timers);
          difference = timer_difference;
+         ripe = timer_ripe;
        }
       else
        {
          chosen_timer = idle_timer;
          idle_timers = XCDR (idle_timers);
          difference = idle_timer_difference;
+         ripe = idle_timer_ripe;
        }
-      vector = XVECTOR (chosen_timer)->contents;
 
       /* If timer is ripe, run it if it hasn't been run.  */
-      if (EMACS_TIME_NEG_P (difference)
-         || (EMACS_SECS (difference) == 0
-             && EMACS_USECS (difference) == 0))
+      if (ripe)
        {
+         vector = XVECTOR (chosen_timer)->contents;
          if (NILP (vector[0]))
            {
              ptrdiff_t count = SPECPDL_INDEX ();
@@ -4508,7 +4500,7 @@ timer_check_2 (void)
    timer list for the time being.
 
    Returns the time to wait until the next timer fires.
-   If no timer is active, return -1.
+   If no timer is active, return an invalid value.
 
    As long as any timer is ripe, we run it.  */
 
@@ -4521,33 +4513,29 @@ timer_check (void)
     {
       nexttime = timer_check_2 ();
     }
-  while (EMACS_SECS (nexttime) == 0 && EMACS_USECS (nexttime) == 0);
+  while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
 
   return nexttime;
 }
 
 DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
        doc: /* Return the current length of Emacs idleness, or nil.
-The value when Emacs is idle is a list of three integers.  The first has
-the most significant 16 bits of the seconds, while the second has the least
-significant 16 bits.  The third integer gives the microsecond count.
+The value when Emacs is idle is a list of four integers (HIGH LOW USEC PSEC)
+in the same style as (current-time).
 
 The value when Emacs is not idle is nil.
 
-The microsecond count is zero on systems that do not provide
-resolution finer than a second.  */)
+NSEC is a multiple of the system clock resolution.  */)
   (void)
 {
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     {
       EMACS_TIME now, idleness_now;
 
       EMACS_GET_TIME (now);
       EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
 
-      return list3 (make_number ((EMACS_SECS (idleness_now) >> 16) & 0xffff),
-                   make_number ((EMACS_SECS (idleness_now) >> 0)  & 0xffff),
-                   make_number (EMACS_USECS (idleness_now)));
+      return make_lisp_time (idleness_now);
     }
 
   return Qnil;
@@ -10735,7 +10723,7 @@ stuff_buffered_input (Lisp_Object stuffstring)
 }
 \f
 void
-set_waiting_for_input (struct timeval *time_to_clear)
+set_waiting_for_input (EMACS_TIME *time_to_clear)
 {
   input_available_clear_time = time_to_clear;
 
@@ -11358,7 +11346,7 @@ init_keyboard (void)
   quit_char = Ctl ('g');
   Vunread_command_events = Qnil;
   unread_command_char = -1;
-  EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
+  EMACS_SET_INVALID_TIME (timer_idleness_start_time);
   total_keys = 0;
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
index a88bf10c8bc3488100cb9917e808e44c2688ea76..dd8cdd348b288921d46d13d16a50275e16321354 100644 (file)
@@ -2954,6 +2954,7 @@ EXFUN (Fnarrow_to_region, 2);
 EXFUN (Fwiden, 0);
 EXFUN (Fuser_login_name, 1);
 EXFUN (Fsystem_name, 0);
+extern void time_overflow (void) NO_RETURN;
 EXFUN (Fcurrent_time, 0);
 EXFUN (Fget_internal_run_time, 0);
 extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, int);
@@ -3244,7 +3245,7 @@ EXFUN (Fkill_process, 2);
 EXFUN (Fwaiting_for_user_input_p, 0);
 extern Lisp_Object Qprocessp;
 extern void kill_buffer_processes (Lisp_Object);
-extern int wait_reading_process_output (int, int, int, int,
+extern int wait_reading_process_output (intmax_t, int, int, int,
                                         Lisp_Object,
                                         struct Lisp_Process *,
                                         int);
index 96868c2da89c37f10afc0747e71d914f2b3745ce..fee97044a73c29c447fae42383c2d4e3bc9e48bb 100644 (file)
@@ -601,17 +601,9 @@ read_filtered_event (int no_switch_frame, int ascii_required,
   /* Compute timeout.  */
   if (NUMBERP (seconds))
     {
-      EMACS_TIME wait_time;
-      int sec, usec;
       double duration = extract_float (seconds);
-
-      if (0 < duration)
-       duration_to_sec_usec (duration, &sec, &usec);
-      else
-       sec = usec = 0;
-
+      EMACS_TIME wait_time = EMACS_TIME_FROM_DOUBLE (duration);
       EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (wait_time, sec, usec);
       EMACS_ADD_TIME (end_time, end_time, wait_time);
     }
 
index c9bee400020bdd2b2331472172db2a8ee9cb0a91..66911098ce0cb73179187617e8086a0fda72ee54 100644 (file)
@@ -4070,13 +4070,6 @@ sigprocmask (int how, const sigset_t *new_set, sigset_t *old_set)
 #ifndef HAVE_SELECT
 #include "sysselect.h"
 
-#ifndef EMACS_TIME_ZERO_OR_NEG_P
-#define EMACS_TIME_ZERO_OR_NEG_P(time) \
-  ((long)(time).tv_sec < 0             \
-   || ((time).tv_sec == 0              \
-       && (long)(time).tv_usec <= 0))
-#endif
-
 /* This yields the rest of the current time slice to the task manager.
    It should be called by any code which knows that it has nothing
    useful to do except idle.
@@ -4145,12 +4138,12 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
 
          /* When seconds wrap around, we assume that no more than
             1 minute passed since last `gettime'.  */
-         if (EMACS_TIME_NEG_P (cldiff))
+         if (EMACS_TIME_SIGN (cldiff) < 0)
            EMACS_SET_SECS (cldiff, EMACS_SECS (cldiff) + 60);
          EMACS_SUB_TIME (*timeout, *timeout, cldiff);
 
          /* Stop when timeout value crosses zero.  */
-         if (EMACS_TIME_ZERO_OR_NEG_P (*timeout))
+         if (EMACS_TIME_SIGN (*timeout) <= 0)
            return 0;
          cllast = clnow;
          dos_yield_time_slice ();
index bc535b47d973a6481fcafe49aed3e700f0aadfd8..9158b78e7ba0b02cbb317ee57c3d64689beaa574 100644 (file)
@@ -824,7 +824,8 @@ extern int x_display_pixel_width (struct ns_display_info *);
 
 /* This in nsterm.m */
 extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds,
-                      fd_set *exceptfds, struct timeval *timeout);
+                      fd_set *exceptfds, EMACS_TIME *timeout,
+                     sigset_t *sigmask);
 extern unsigned long ns_get_rgb_color (struct frame *f,
                                        float r, float g, float b, float a);
 extern NSPoint last_mouse_motion_position;
index dd4969a1e2e358768a2f2d89491d44932a52fade..bf14e5c83b12f47867763295f3f12eac03d79924 100644 (file)
@@ -183,7 +183,6 @@ static NSTimer *timed_entry = 0;
 static NSTimer *fd_entry = nil;
 static NSTimer *scroll_repeat_entry = nil;
 static fd_set select_readfds, t_readfds;
-static struct timeval select_timeout;
 static int select_nfds;
 static NSAutoreleasePool *outerpool;
 static struct input_event *emacs_event = NULL;
@@ -381,67 +380,30 @@ ns_init_paths (void)
     }
 }
 
-
-static int
-timeval_subtract (struct timeval *result, struct timeval x, struct timeval y)
-/* --------------------------------------------------------------------------
-   Subtract the `struct timeval' values X and Y, storing the result in RESULT.
-   Return 1 if the difference is negative, otherwise 0.
-   -------------------------------------------------------------------------- */
-{
-  /* Perform the carry for the later subtraction by updating y.
-     This is safer because on some systems
-     the tv_sec member is unsigned.  */
-  if (x.tv_usec < y.tv_usec)
-    {
-      int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
-      y.tv_usec -= 1000000 * nsec;
-      y.tv_sec += nsec;
-    }
-  if (x.tv_usec - y.tv_usec > 1000000)
-    {
-      int nsec = (y.tv_usec - x.tv_usec) / 1000000;
-      y.tv_usec += 1000000 * nsec;
-      y.tv_sec -= nsec;
-    }
-
-  /* Compute the time remaining to wait.  tv_usec is certainly positive.  */
-  result->tv_sec = x.tv_sec - y.tv_sec;
-  result->tv_usec = x.tv_usec - y.tv_usec;
-
-  /* Return indication of whether the result should be considered negative.  */
-  return x.tv_sec < y.tv_sec;
-}
-
 static void
 ns_timeout (int usecs)
 /* --------------------------------------------------------------------------
      Blocking timer utility used by ns_ring_bell
    -------------------------------------------------------------------------- */
 {
-  struct timeval wakeup;
+  EMACS_TIME wakeup, delay;
 
   EMACS_GET_TIME (wakeup);
-
-  /* Compute time to wait until, propagating carry from usecs.  */
-  wakeup.tv_usec += usecs;
-  wakeup.tv_sec += (wakeup.tv_usec / 1000000);
-  wakeup.tv_usec %= 1000000;
+  EMACS_SET_SECS_USECS (delay, 0, usecs);
+  EMACS_ADD_TIME (wakeup, wakeup, delay);
 
   /* Keep waiting until past the time wakeup.  */
   while (1)
     {
-      struct timeval timeout;
+      EMACS_TIME timeout;
 
       EMACS_GET_TIME (timeout);
-
-      /* In effect, timeout = wakeup - timeout.
-        Break if result would be negative.  */
-      if (timeval_subtract (&timeout, wakeup, timeout))
+      if (EMACS_TIME_LE (wakeup, timeout))
        break;
+      EMACS_SUB_TIME (timeout, wakeup, timeout);
 
       /* Try to wait that long--but we might wake up sooner.  */
-      select (0, NULL, NULL, NULL, &timeout);
+      pselect (0, NULL, NULL, NULL, &timeout, NULL);
     }
 }
 
@@ -3537,7 +3499,7 @@ ns_read_socket (struct terminal *terminal, int expected,
 
 int
 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
-           fd_set *exceptfds, struct timeval *timeout)
+           fd_set *exceptfds, EMACS_TIME *timeout, sigset_t *sigmask)
 /* --------------------------------------------------------------------------
      Replacement for select, checking for events
    -------------------------------------------------------------------------- */
@@ -3545,12 +3507,14 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
   int result;
   double time;
   NSEvent *ev;
+  struct timespec select_timeout;
+
 /*  NSTRACE (ns_select); */
 
   if (NSApp == nil || inNsSelect == 1 /* || ([NSApp isActive] == NO &&
                       [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
  inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */)
-    return select (nfds, readfds, writefds, exceptfds, timeout);
+    return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
 
   /* Save file descriptor set, which gets overwritten in calls to select ()
      Note, this is called from process.c, and only readfds is ever set */
@@ -3563,8 +3527,9 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
     select_nfds = 0;
 
     /* Try an initial select for pending data on input files */
-  select_timeout.tv_sec = select_timeout.tv_usec = 0;
-  result = select (nfds, readfds, writefds, exceptfds, &select_timeout);
+  select_timeout.tv_sec = select_timeout.tv_nsec = 0;
+  result = pselect (nfds, readfds, writefds, exceptfds,
+                   &select_timeout, sigmask);
   if (result)
     return result;
 
@@ -3573,7 +3538,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
 
     /* set a timeout and run the main AppKit event loop while continuing
        to monitor the files */
-  time = ((double) timeout->tv_sec) + ((double) timeout->tv_usec)/1000000.0;
+  time = EMACS_TIME_TO_DOUBLE (*timeout);
   timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
                                            target: NSApp
                                          selector: @selector (timeout_handler:)
@@ -3581,7 +3546,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
                                           repeats: YES] /* for safe removal */
                                                          retain];
 
-  /* set a periodic task to try the select () again */
+  /* set a periodic task to try the pselect () again */
   fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1
                                                target: NSApp
                                              selector: @selector (fd_handler:)
@@ -3623,7 +3588,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
         }
       else
         {
-          /* Received back from select () in fd_handler; copy the results */
+          /* Received back from pselect () in fd_handler; copy the results */
           if (readfds)
             memcpy (readfds, &select_readfds, sizeof (fd_set));
           return t;
@@ -4603,6 +4568,7 @@ ns_term_shutdown (int sig)
    -------------------------------------------------------------------------- */
 {
   int result;
+  struct timespec select_timeout;
   /* NSTRACE (fd_handler); */
 
   if (select_nfds == 0)
@@ -4610,9 +4576,8 @@ ns_term_shutdown (int sig)
 
   memcpy (&t_readfds, &select_readfds, sizeof (fd_set));
 
-  select_timeout.tv_sec = select_timeout.tv_usec = 0;
-  result = select (select_nfds, &t_readfds, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
-                  &select_timeout);
+  select_timeout.tv_sec = select_timeout.tv_nsec = 0;
+  result = pselect (select_nfds, &t_readfds, NULL, NULL, &select_timeout, NULL);
   if (result)
     {
       memcpy (&select_readfds, &t_readfds, sizeof (fd_set));
index cb89cae99feec5f2fff97aecc90834e3eee8fc04..0ee0e499d6e8e4a48a1aaf28ed808655808fc5a9 100644 (file)
@@ -228,13 +228,11 @@ static EMACS_INT update_tick;
 #endif
 
 #if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING)
-#ifdef EMACS_HAS_USECS
 #define ADAPTIVE_READ_BUFFERING
 #endif
-#endif
 
 #ifdef ADAPTIVE_READ_BUFFERING
-#define READ_OUTPUT_DELAY_INCREMENT 10000
+#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100)
 #define READ_OUTPUT_DELAY_MAX       (READ_OUTPUT_DELAY_INCREMENT * 5)
 #define READ_OUTPUT_DELAY_MAX_MAX   (READ_OUTPUT_DELAY_INCREMENT * 7)
 
@@ -3291,7 +3289,7 @@ usage: (make-network-process &rest ARGS)  */)
        {
          /* Unlike most other syscalls connect() cannot be called
             again.  (That would return EALREADY.)  The proper way to
-            wait for completion is select(). */
+            wait for completion is pselect(). */
          int sc;
          socklen_t len;
          SELECT_TYPE fdset;
@@ -3299,8 +3297,7 @@ usage: (make-network-process &rest ARGS)  */)
          FD_ZERO (&fdset);
          FD_SET (s, &fdset);
          QUIT;
-         sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0,
-                      (EMACS_TIME *)0);
+         sc = pselect (s + 1, NULL, &fdset, NULL, NULL, NULL);
          if (sc == -1)
            {
              if (errno == EINTR)
@@ -3961,7 +3958,8 @@ If JUST-THIS-ONE is an integer, don't run any timers either.
 Return non-nil if we received any output before the timeout expired.  */)
   (register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one)
 {
-  int secs = -1, usecs = 0;
+  intmax_t secs;
+  int nsecs;
 
   if (! NILP (process))
     CHECK_PROCESS (process);
@@ -3980,17 +3978,36 @@ Return non-nil if we received any output before the timeout expired.  */)
        }
     }
 
+  secs = 0;
+  nsecs = -1;
+
   if (!NILP (seconds))
     {
-      double duration = extract_float (seconds);
-      if (0 < duration)
-       duration_to_sec_usec (duration, &secs, &usecs);
+      if (INTEGERP (seconds))
+       {
+         if (0 < XINT (seconds))
+           {
+             secs = XINT (seconds);
+             nsecs = 0;
+           }
+       }
+      else if (FLOATP (seconds))
+       {
+         if (0 < XFLOAT_DATA (seconds))
+           {
+             EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds));
+             secs = min (EMACS_SECS (t), INTMAX_MAX);
+             nsecs = EMACS_NSECS (t);
+           }
+       }
+      else
+       wrong_type_argument (Qnumberp, seconds);
     }
-  else if (!NILP (process))
-    secs = 0;
+  else if (! NILP (process))
+    nsecs = 0;
 
   return
-    (wait_reading_process_output (secs, usecs, 0, 0,
+    (wait_reading_process_output (secs, nsecs, 0, 0,
                                  Qnil,
                                  !NILP (process) ? XPROCESS (process) : NULL,
                                  NILP (just_this_one) ? 0 :
@@ -4231,34 +4248,19 @@ wait_reading_process_output_1 (void)
 {
 }
 
-/* Use a wrapper around select to work around a bug in gdb 5.3.
-   Normally, the wrapper is optimized away by inlining.
-
-   If emacs is stopped inside select, the gdb backtrace doesn't
-   show the function which called select, so it is practically
-   impossible to step through wait_reading_process_output.  */
-
-#ifndef select
-static inline int
-select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo)
-{
-  return select (n, rfd, wfd, xfd, tmo);
-}
-#define select select_wrapper
-#endif
-
 /* Read and dispose of subprocess output while waiting for timeout to
    elapse and/or keyboard input to be available.
 
    TIME_LIMIT is:
-     timeout in seconds, or
-     zero for no limit, or
-     -1 means gobble data immediately available but don't wait for any.
+     timeout in seconds
+     If negative, gobble data immediately available but don't wait for any.
 
-   MICROSECS is:
-     an additional duration to wait, measured in microseconds.
-     If this is nonzero and time_limit is 0, then the timeout
-     consists of MICROSECS only.
+   NSECS is:
+     an additional duration to wait, measured in nanoseconds
+     If TIME_LIMIT is zero, then:
+       If NSECS == 0, there is no limit.
+       If NSECS > 0, the timeout consists of NSEC only.
+       If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
 
    READ_KBD is a lisp value:
      0 to ignore keyboard input, or
@@ -4285,7 +4287,7 @@ select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tm
    Otherwise, return true if we received input from any process.  */
 
 int
-wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                             int do_display,
                             Lisp_Object wait_for_cell,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
@@ -4305,7 +4307,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
   FD_ZERO (&Available);
   FD_ZERO (&Writeok);
 
-  if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
+  if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
       && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
     message ("Blocking call to accept-process-output with quit inhibited!!");
 
@@ -4317,12 +4319,20 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                         make_number (waiting_for_user_input_p));
   waiting_for_user_input_p = read_kbd;
 
+  if (time_limit < 0)
+    {
+      time_limit = 0;
+      nsecs = -1;
+    }
+  else if (TYPE_MAXIMUM (time_t) < time_limit)
+    time_limit = TYPE_MAXIMUM (time_t);
+
   /* Since we may need to wait several times,
      compute the absolute time to return at.  */
-  if (time_limit || microsecs)
+  if (time_limit || nsecs) /* FIXME neither should be negative, no? */
     {
       EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
+      EMACS_SET_SECS_NSECS (timeout, time_limit, nsecs);
       EMACS_ADD_TIME (end_time, end_time, timeout);
     }
 
@@ -4346,7 +4356,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 
       /* Compute time from now till when time limit is up */
       /* Exit if already run out */
-      if (time_limit == -1)
+      if (nsecs < 0)
        {
          /* -1 specified for timeout means
             gobble output available now
@@ -4354,12 +4364,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 
          EMACS_SET_SECS_USECS (timeout, 0, 0);
        }
-      else if (time_limit || microsecs)
+      else if (time_limit || nsecs)
        {
          EMACS_GET_TIME (timeout);
-         EMACS_SUB_TIME (timeout, end_time, timeout);
-         if (EMACS_TIME_NEG_P (timeout))
+         if (EMACS_TIME_LE (end_time, timeout))
            break;
+         EMACS_SUB_TIME (timeout, end_time, timeout);
        }
       else
        {
@@ -4405,21 +4415,22 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              && requeued_events_pending_p ())
            break;
 
-         if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+         /* If time_limit is negative, we are not going to wait at all.  */
+         if (0 <= nsecs)
            {
-             EMACS_TIME difference;
-             EMACS_SUB_TIME (difference, timer_delay, timeout);
-             if (EMACS_TIME_NEG_P (difference))
+             if (EMACS_TIME_VALID_P (timer_delay))
                {
-                 timeout = timer_delay;
-                 timeout_reduced_for_timers = 1;
+                 if (EMACS_TIME_LT (timer_delay, timeout))
+                   {
+                     timeout = timer_delay;
+                     timeout_reduced_for_timers = 1;
+                   }
+               }
+             else
+               {
+                 /* This is so a breakpoint can be put here.  */
+                 wait_reading_process_output_1 ();
                }
-           }
-         /* If time_limit is -1, we are not going to wait at all.  */
-         else if (time_limit != -1)
-           {
-             /* This is so a breakpoint can be put here.  */
-             wait_reading_process_output_1 ();
            }
        }
 
@@ -4448,14 +4459,14 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
          Ctemp = write_mask;
 
          EMACS_SET_SECS_USECS (timeout, 0, 0);
-         if ((select (max (max_process_desc, max_input_desc) + 1,
-                      &Atemp,
+         if ((pselect (max (max_process_desc, max_input_desc) + 1,
+                       &Atemp,
 #ifdef NON_BLOCKING_CONNECT
-                      (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
+                       (num_pending_connects > 0 ? &Ctemp : NULL),
 #else
-                      (SELECT_TYPE *)0,
+                       NULL,
 #endif
-                      (SELECT_TYPE *)0, &timeout)
+                       NULL, &timeout, NULL)
               <= 0))
            {
              /* It's okay for us to do this and then continue with
@@ -4578,9 +4589,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
             Vprocess_adaptive_read_buffering is nil.  */
          if (process_output_skip && check_delay > 0)
            {
-             int usecs = EMACS_USECS (timeout);
-             if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX)
-               usecs = READ_OUTPUT_DELAY_MAX;
+             int nsecs = EMACS_NSECS (timeout);
+             if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX)
+               nsecs = READ_OUTPUT_DELAY_MAX;
              for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++)
                {
                  proc = chan_process[channel];
@@ -4595,11 +4606,11 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                        continue;
                      FD_CLR (channel, &Available);
                      XPROCESS (proc)->read_output_skip = 0;
-                     if (XPROCESS (proc)->read_output_delay < usecs)
-                       usecs = XPROCESS (proc)->read_output_delay;
+                     if (XPROCESS (proc)->read_output_delay < nsecs)
+                       nsecs = XPROCESS (proc)->read_output_delay;
                    }
                }
-             EMACS_SET_SECS_USECS (timeout, 0, usecs);
+             EMACS_SET_SECS_NSECS (timeout, 0, nsecs);
              process_output_skip = 0;
            }
 #endif
@@ -4608,12 +4619,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 #elif defined (HAVE_NS)
          nfds = ns_select
 #else
-         nfds = select
+         nfds = pselect
 #endif
             (max (max_process_desc, max_input_desc) + 1,
              &Available,
              (check_write ? &Writeok : (SELECT_TYPE *)0),
-             (SELECT_TYPE *)0, &timeout);
+             NULL, &timeout, NULL);
 
 #ifdef HAVE_GNUTLS
           /* GnuTLS buffers data internally.  In lowat mode it leaves
@@ -4671,7 +4682,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       /*  If we woke up due to SIGWINCH, actually change size now.  */
       do_pending_window_change (0);
 
-      if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
+      if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
        /* We wanted the full specified time, so return now.  */
        break;
       if (nfds < 0)
@@ -4823,7 +4834,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              if (wait_channel == channel)
                {
                  wait_channel = -1;
-                 time_limit = -1;
+                 nsecs = -1;
                  got_some_input = 1;
                }
              proc = chan_process[channel];
@@ -5680,11 +5691,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
 
                      /* Put what we should have written in wait_queue.  */
                      write_queue_push (p, cur_object, cur_buf, cur_len, 1);
-#ifdef EMACS_HAS_USECS
-                     wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0);
-#else
-                     wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0);
-#endif
+                     wait_reading_process_output (0, 20 * 1000 * 1000,
+                                                  0, 0, Qnil, NULL, 0);
                      /* Reread queue, to see what is left.  */
                      break;
                    }
@@ -6825,9 +6833,15 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
    Wait for timeout to elapse and/or keyboard input to be available.
 
    time_limit is:
-     timeout in seconds, or
-     zero for no limit, or
-     -1 means gobble data immediately available but don't wait for any.
+     timeout in seconds
+     If negative, gobble data immediately available but don't wait for any.
+
+   nsec is:
+     an additional duration to wait, measured in nanoseconds
+     If TIME_LIMIT is zero, then:
+       If NSEC == 0, there is no limit.
+       If NSEC > 0, the timeout consists of NSEC only.
+       If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
 
    read_kbd is a Lisp_Object:
      0 to ignore keyboard input, or
@@ -6844,7 +6858,7 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
    Return true if we received input from any process.  */
 
 int
-wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                             int do_display,
                             Lisp_Object wait_for_cell,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
@@ -6854,11 +6868,19 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
   SELECT_TYPE waitchannels;
   int xerrno;
 
+  if (time_limit < 0)
+    {
+      time_limit = 0;
+      nsecs = -1;
+    }
+  else if (TYPE_MAXIMUM (time_t) < time_limit)
+    time_limit = TYPE_MAXIMUM (time_t);
+
   /* What does time_limit really mean?  */
-  if (time_limit || microsecs)
+  if (time_limit || nsecs) /* FIXME: what if negative? */
     {
       EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
+      EMACS_SET_SECS_NSECS (timeout, time_limit, nsecs);
       EMACS_ADD_TIME (end_time, end_time, timeout);
     }
 
@@ -6884,7 +6906,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 
       /* Compute time from now till when time limit is up */
       /* Exit if already run out */
-      if (time_limit == -1)
+      if (nsecs < 0)
        {
          /* -1 specified for timeout means
             gobble output available now
@@ -6892,12 +6914,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 
          EMACS_SET_SECS_USECS (timeout, 0, 0);
        }
-      else if (time_limit || microsecs)
+      else if (time_limit || nsecs)
        {
          EMACS_GET_TIME (timeout);
-         EMACS_SUB_TIME (timeout, end_time, timeout);
-         if (EMACS_TIME_NEG_P (timeout))
+         if (EMACS_TIME_LE (end_time, timeout))
            break;
+         EMACS_SUB_TIME (timeout, end_time, timeout);
        }
       else
        {
@@ -6930,11 +6952,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              && requeued_events_pending_p ())
            break;
 
-         if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+         if (EMACS_TIME_VALID_P (timer_delay) && 0 <= nsecs)
            {
-             EMACS_TIME difference;
-             EMACS_SUB_TIME (difference, timer_delay, timeout);
-             if (EMACS_TIME_NEG_P (difference))
+             if (EMACS_TIME_LT (timer_delay, timeout))
                {
                  timeout = timer_delay;
                  timeout_reduced_for_timers = 1;
@@ -6970,8 +6990,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
          FD_ZERO (&waitchannels);
        }
       else
-       nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
-                      &timeout);
+       nfds = pselect (1, &waitchannels, NULL, NULL, &timeout, NULL);
 
       xerrno = errno;
 
@@ -6981,7 +7000,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       /*  If we woke up due to SIGWINCH, actually change size now.  */
       do_pending_window_change (0);
 
-      if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
+      if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
        /* We waited the full specified time, so return now.  */
        break;
 
@@ -7284,19 +7303,20 @@ integer or floating point values.
  majflt  -- number of major page faults (number)
  cminflt -- cumulative number of minor page faults (number)
  cmajflt -- cumulative number of major page faults (number)
- utime   -- user time used by the process, in the (HIGH LOW USEC) format
- stime   -- system time used by the process, in the (HIGH LOW USEC) format
- time    -- sum of utime and stime, in the (HIGH LOW USEC) format
- cutime  -- user time used by the process and its children, (HIGH LOW USEC)
- cstime  -- system time used by the process and its children, (HIGH LOW USEC)
- ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
+ utime   -- user time used by the process, in (current-time) format,
+              which is a list of integers (HIGH LOW USEC PSEC)
+ stime   -- system time used by the process (current-time)
+ time    -- sum of utime and stime (current-time)
+ cutime  -- user time used by the process and its children (current-time)
+ cstime  -- system time used by the process and its children (current-time)
+ ctime   -- sum of cutime and cstime (current-time)
  pri     -- priority of the process (number)
  nice    -- nice value of the process (number)
  thcount -- process thread count (number)
- start   -- time the process started, in the (HIGH LOW USEC) format
+ start   -- time the process started (current-time)
  vsize   -- virtual memory size of the process in KB's (number)
  rss     -- resident set size of the process in KB's (number)
- etime   -- elapsed time the process is running, in (HIGH LOW USEC) format
+ etime   -- elapsed time the process is running, in (HIGH LOW USEC PSEC) format
  pcpu    -- percents of CPU time used by the process (floating-point number)
  pmem    -- percents of total physical memory used by process's resident set
               (floating-point number)
index ae4b6b61c9458c085e7ed6a80260f8cf6d881324..649056a99ff34190bf6783fa08f25df96165bbe5 100644 (file)
@@ -106,8 +106,8 @@ struct Lisp_Process
        On some systems, e.g. GNU/Linux, Emacs is seen as
        an interactive app also when reading process output, meaning
        that process output can be read in as little as 1 byte at a
-       time.  Value is micro-seconds to delay reading output from
-       this process.  Range is 0 .. 50000.  */
+       time.  Value is nanoseconds to delay reading output from
+       this process.  Range is 0 .. 50 * 1000 * 1000.  */
     int read_output_delay;
     /* Should we delay reading output from this process.
        Initialized from `Vprocess_adaptive_read_buffering'.
index 3356582de0cd17c1c96f11e9dd555ba6528edf6c..8d1c3d0ca3c023e12d0e79fcf9aa4e7b28fab27b 100644 (file)
@@ -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);
@@ -2066,30 +2053,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 */
 
 \f
+/* 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);
 }
 \f
 /* 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);
 
index f9b9fc00b35a091280a3385a1789aed5cf7f48c3..e1e5839cfe4e2071499bcca9e05e5d72e89ceb55 100644 (file)
@@ -16,7 +16,6 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#ifdef HAVE_SYS_SELECT_H
 #if defined (DARWIN_OS)
 #undef init_process
 #endif
@@ -24,7 +23,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #if defined (DARWIN_OS)
 #define init_process emacs_init_process
 #endif
-#endif
 
 /* The w32 build defines select stuff in w32.h, which is included
    where w32 needs it, but not where sysselect.h is included.  The w32
@@ -52,4 +50,3 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #if !defined (HAVE_SELECT)
 #define select sys_select
 #endif
-
index 9e7a1173a20dd06cf2eb23398171465c80e19a6b..dd0d77c827d9f34d0e19fa6bb77e3b6bb461657b 100644 (file)
@@ -19,16 +19,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifndef EMACS_SYSTIME_H
 #define EMACS_SYSTIME_H
 
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
+#include <timespec.h>
 
 #ifdef emacs
 # ifdef HAVE_X_WINDOWS
@@ -48,91 +39,64 @@ typedef unsigned long Time;
 #endif
 #endif
 \f
-/* EMACS_TIME is the type to use to represent temporal intervals -
-   struct timeval on some systems, int on others.  It can be passed as
-   the timeout argument to the select  system call.
+/* The type to use to represent temporal intervals.  It can be passed
+   as the timeout argument to the pselect system call.  */
+#define EMACS_TIME struct timespec
 
-   EMACS_SECS (TIME) is an rvalue for the seconds component of TIME.
+/* Resolution of EMACS_TIME time stamps (in units per second), and log
+   base 10 of the resolution.  The log must be a positive integer.  */
+#define EMACS_TIME_RESOLUTION          1000000000
+#define LOG10_EMACS_TIME_RESOLUTION    9
+
+/* EMACS_SECS (TIME) is an rvalue for the seconds component of TIME.
+   EMACS_SECS_ADDR (time) is the address of the seconds component.
    EMACS_SET_SECS (TIME, SECONDS) sets that to SECONDS.
 
-   EMACS_HAS_USECS is defined if EMACS_TIME has a usecs component.
-   EMACS_USECS (TIME) is an rvalue for the microseconds component of TIME.
-       This returns zero if EMACS_TIME doesn't have a microseconds component.
-   EMACS_SET_USECS (TIME, MICROSECONDS) sets that to MICROSECONDS.
-       This does nothing if EMACS_TIME doesn't have a microseconds component.
+   EMACS_NSECS (TIME) is an rvalue for the nanoseconds component of TIME.
+   EMACS_SET_NSECS (TIME, NANOSECONDS) sets that to NANOSECONDS.
 
-   EMACS_SET_SECS_USECS (TIME, SECS, USECS) sets both components of TIME.
+   EMACS_SET_SECS_NSECS (TIME, SECS, NSECS) sets both components of TIME.  */
+#define EMACS_SECS(time)                   ((time).tv_sec  + 0)
+#define EMACS_NSECS(time)                  ((time).tv_nsec + 0)
+#define EMACS_SECS_ADDR(time)              (&(time).tv_sec)
+#define EMACS_SET_SECS(time, seconds)      ((time).tv_sec  = (seconds))
+#define EMACS_SET_NSECS(time, ns)          ((time).tv_nsec = (ns))
+#define EMACS_SET_SECS_NSECS(time, s, ns)                              \
+  ((void) (EMACS_SET_SECS (time, s), EMACS_SET_NSECS (time, ns)))
 
-   EMACS_GET_TIME (TIME) stores the current system time in TIME, which
-       should be an lvalue.
+/* Convenience macros for older code that counts microseconds.  */
+#define EMACS_SET_USECS(time, us)  ((void) EMACS_SET_NSECS (time, (us) * 1000))
+#define EMACS_SET_SECS_USECS(time, secs, usecs)                \
+  (EMACS_SET_SECS (time, secs), EMACS_SET_USECS (time, usecs))
 
-   EMACS_ADD_TIME (DEST, SRC1, SRC2) adds SRC1 to SRC2 and stores the
-       result in DEST.  SRC should not be negative.
+/* Set TIME to an invalid time stamp.  */
+#define EMACS_SET_INVALID_TIME(time)       EMACS_SET_SECS_NSECS(time, 0, -1)
 
-   EMACS_SUB_TIME (DEST, SRC1, SRC2) subtracts SRC2 from SRC1 and
-       stores the result in DEST.  SRC should not be negative.
-   EMACS_TIME_NEG_P (TIME) is true if TIME is negative.
+/* Set TIME to the current system time.  */
+#define EMACS_GET_TIME(time)               gettime (&(time))
 
-*/
+/* Put into DEST the result of adding SRC1 to SRC2, or of subtracting
+   SRC2 from SRC1.  On overflow, store an extremal value.  */
+#define EMACS_ADD_TIME(dest, src1, src2) ((dest) = timespec_add (src1, src2))
+#define EMACS_SUB_TIME(dest, src1, src2) ((dest) = timespec_sub (src1, src2))
 
-#ifdef HAVE_TIMEVAL
+/* Return the sign of the valid time stamp TIME, either -1, 0, or 1.  */
+#define EMACS_TIME_SIGN(time)          timespec_sign (time)
 
-#define EMACS_HAS_USECS
+/* Return 1 if TIME is a valid time stamp.  */
+#define EMACS_TIME_VALID_P(time)       (0 <= (time).tv_nsec)
 
-#define EMACS_TIME struct timeval
-#define EMACS_SECS(time)                   ((time).tv_sec  + 0)
-#define EMACS_USECS(time)                  ((time).tv_usec + 0)
-#define EMACS_SET_SECS(time, seconds)      ((time).tv_sec  = (seconds))
-#define EMACS_SET_USECS(time, microseconds) ((time).tv_usec = (microseconds))
-
-/* On SVR4, the compiler may complain if given this extra BSD arg.  */
-#ifdef GETTIMEOFDAY_ONE_ARGUMENT
-#define EMACS_GET_TIME(time) gettimeofday (&(time))
-#else /* not GETTIMEOFDAY_ONE_ARGUMENT */
-/* Presumably the second arg is ignored.  */
-#define EMACS_GET_TIME(time) gettimeofday (&(time), NULL)
-#endif /* not GETTIMEOFDAY_ONE_ARGUMENT */
-
-#define EMACS_ADD_TIME(dest, src1, src2)               \
-  do {                                                 \
-    (dest).tv_sec  = (src1).tv_sec  + (src2).tv_sec;   \
-    (dest).tv_usec = (src1).tv_usec + (src2).tv_usec;  \
-    if ((dest).tv_usec > 1000000)                      \
-      (dest).tv_usec -= 1000000, (dest).tv_sec++;      \
-  } while (0)
-
-#define EMACS_SUB_TIME(dest, src1, src2)               \
-  do {                                                 \
-    (dest).tv_sec  = (src1).tv_sec  - (src2).tv_sec;   \
-    (dest).tv_usec = (src1).tv_usec - (src2).tv_usec;  \
-    if ((dest).tv_usec < 0)                            \
-      (dest).tv_usec += 1000000, (dest).tv_sec--;      \
-  } while (0)
-
-#define EMACS_TIME_NEG_P(time)                                 \
-  ((long)(time).tv_sec < 0                                     \
-   || ((time).tv_sec == 0                                      \
-       && (long)(time).tv_usec < 0))
-
-#else /* ! defined (HAVE_TIMEVAL) */
-
-#define EMACS_TIME int
-#define EMACS_SECS(time)                   (time)
-#define EMACS_USECS(time)                  0
-#define EMACS_SET_SECS(time, seconds)      ((time) = (seconds))
-#define EMACS_SET_USECS(time, usecs)       0
-
-#define EMACS_GET_TIME(t) ((t) = time ((long *) 0))
-#define EMACS_ADD_TIME(dest, src1, src2) ((dest) = (src1) + (src2))
-#define EMACS_SUB_TIME(dest, src1, src2) ((dest) = (src1) - (src2))
-#define EMACS_TIME_NEG_P(t) ((t) < 0)
-
-#endif /* ! defined (HAVE_TIMEVAL) */
+/* Convert the double D to the greatest EMACS_TIME not greater than D.
+   On overflow, return an extremal value.  Return the minimum
+   EMACS_TIME if D is not a number.  */
+#define EMACS_TIME_FROM_DOUBLE(d)      dtotimespec (d)
 
-#define EMACS_SET_SECS_USECS(time, secs, usecs)                \
-  (EMACS_SET_SECS (time, secs), EMACS_SET_USECS (time, usecs))
+/* Convert the Emacs time T to an approximate double value D.  */
+#define EMACS_TIME_TO_DOUBLE(t)                timespectod (t)
 
-extern int set_file_times (const char *, EMACS_TIME, EMACS_TIME);
+/* defined in sysdep.c */
+extern int set_file_times (int, const char *, EMACS_TIME, EMACS_TIME);
+extern struct timeval make_timeval (EMACS_TIME);
 
 /* defined in keyboard.c */
 extern void set_waiting_for_input (EMACS_TIME *);
@@ -141,29 +105,20 @@ extern void set_waiting_for_input (EMACS_TIME *);
    happen when this files is used outside the src directory).
    Use GCPRO1 to determine if lisp.h was included.  */
 #ifdef GCPRO1
-/* defined in editfns.c*/
-extern Lisp_Object make_time (time_t);
-extern int lisp_time_argument (Lisp_Object, time_t *, int *);
+/* defined in editfns.c */
+extern Lisp_Object make_lisp_time (EMACS_TIME);
+extern int decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object,
+                                  Lisp_Object, EMACS_TIME *, int *);
+extern EMACS_TIME lisp_time_argument (Lisp_Object, int *);
 #endif
 
-/* Compare times T1 and T2.  Value is 0 if T1 and T2 are the same.
-   Value is < 0 if T1 is less than T2.  Value is > 0 otherwise.  (Cast
-   to long is for those platforms where time_t is an unsigned
-   type, and where otherwise T1 will always be grater than T2.)  */
-
-#define EMACS_TIME_CMP(T1, T2)                         \
-  ((long)EMACS_SECS (T1) - (long)EMACS_SECS (T2)       \
-   + (EMACS_SECS (T1) == EMACS_SECS (T2)               \
-      ? EMACS_USECS (T1) - EMACS_USECS (T2)            \
-      : 0))
-
 /* Compare times T1 and T2 for equality, inequality etc.  */
 
-#define EMACS_TIME_EQ(T1, T2) (EMACS_TIME_CMP (T1, T2) == 0)
-#define EMACS_TIME_NE(T1, T2) (EMACS_TIME_CMP (T1, T2) != 0)
-#define EMACS_TIME_GT(T1, T2) (EMACS_TIME_CMP (T1, T2) > 0)
-#define EMACS_TIME_GE(T1, T2) (EMACS_TIME_CMP (T1, T2) >= 0)
-#define EMACS_TIME_LT(T1, T2) (EMACS_TIME_CMP (T1, T2) < 0)
-#define EMACS_TIME_LE(T1, T2) (EMACS_TIME_CMP (T1, T2) <= 0)
+#define EMACS_TIME_EQ(T1, T2) (timespec_cmp (T1, T2) == 0)
+#define EMACS_TIME_NE(T1, T2) (timespec_cmp (T1, T2) != 0)
+#define EMACS_TIME_GT(T1, T2) (timespec_cmp (T1, T2) > 0)
+#define EMACS_TIME_GE(T1, T2) (timespec_cmp (T1, T2) >= 0)
+#define EMACS_TIME_LT(T1, T2) (timespec_cmp (T1, T2) < 0)
+#define EMACS_TIME_LE(T1, T2) (timespec_cmp (T1, T2) <= 0)
 
 #endif /* EMACS_SYSTIME_H */
index 5f80718119941c0ca72634afaab77d6af65a49dd..1a2524fd29794caa291e124389f04015fc247cbc 100644 (file)
@@ -24,6 +24,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <ctype.h>
 #include <errno.h>
 #include <sys/file.h>
+#include <sys/time.h>
 #include <unistd.h>
 #include <signal.h>
 #include <setjmp.h>
@@ -2611,6 +2612,18 @@ term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
   return 0;
 }
 
+/* Return the Time that corresponds to T.  Wrap around on overflow.  */
+static Time
+timeval_to_Time (struct timeval const *t)
+{
+  Time s_1000, ms;
+
+  s_1000 = t->tv_sec;
+  s_1000 *= 1000;
+  ms = t->tv_usec / 1000;
+  return s_1000 + ms;
+}
+
 /* Return the current position of the mouse.
 
    Set *f to the frame the mouse is in, or zero if the mouse is in no
@@ -2630,7 +2643,6 @@ term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
                     Lisp_Object *y, Time *timeptr)
 {
   struct timeval now;
-  Time sec, usec;
 
   *fp = SELECTED_FRAME ();
   (*fp)->mouse_moved = 0;
@@ -2641,9 +2653,7 @@ term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
   XSETINT (*x, last_mouse_x);
   XSETINT (*y, last_mouse_y);
   gettimeofday(&now, 0);
-  sec = now.tv_sec;
-  usec = now.tv_usec;
-  *timeptr = (sec * 1000) + (usec / 1000);
+  *timeptr = timeval_to_Time (&now);
 }
 
 /* Prepare a mouse-event in *RESULT for placement in the input queue.
@@ -2667,7 +2677,7 @@ term_mouse_click (struct input_event *result, Gpm_Event *event,
       }
     }
   gettimeofday(&now, 0);
-  result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
+  result->timestamp = timeval_to_Time (&now);
 
   if (event->type & GPM_UP)
     result->modifiers = up_modifier;
index 1cb048690ba2f1237e42dd578065bd3771d42287..ae9025c298ef4320cb2cf04815cb733215ae762d 100644 (file)
@@ -226,7 +226,7 @@ record_first_change (void)
     base_buffer = base_buffer->base_buffer;
 
   BVAR (current_buffer, undo_list) =
-    Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)),
+    Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)),
           BVAR (current_buffer, undo_list));
 }
 
@@ -505,10 +505,23 @@ Return what remains of the list.  */)
              cdr = XCDR (next);
              if (EQ (car, Qt))
                {
-                 /* Element (t high . low) records previous modtime.  */
+                 /* Element (t . TIME) records previous modtime.
+                    Preserve any flag of NONEXISTENT_MODTIME_NSECS or
+                    UNKNOWN_MODTIME_NSECS.  */
                  struct buffer *base_buffer = current_buffer;
-                 time_t mod_time;
-                 CONS_TO_INTEGER (cdr, time_t, mod_time);
+                 EMACS_TIME mod_time;
+
+                 if (CONSP (cdr)
+                     && CONSP (XCDR (cdr))
+                     && CONSP (XCDR (XCDR (cdr)))
+                     && CONSP (XCDR (XCDR (XCDR (cdr))))
+                     && INTEGERP (XCAR (XCDR (XCDR (XCDR (cdr)))))
+                     && XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) < 0)
+                   EMACS_SET_SECS_NSECS
+                     (mod_time, 0,
+                      XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000);
+                 else
+                   mod_time = lisp_time_argument (cdr, 0);
 
                  if (current_buffer->base_buffer)
                    base_buffer = current_buffer->base_buffer;
@@ -516,7 +529,7 @@ Return what remains of the list.  */)
                  /* If this records an obsolete save
                     (not matching the actual disk file)
                     then don't mark unmodified.  */
-                 if (mod_time != base_buffer->modtime)
+                 if (EMACS_TIME_NE (mod_time, base_buffer->modtime))
                    continue;
 #ifdef CLASH_DETECTION
                  Funlock_buffer ();
index 248a91463e894d75f360b396cbc05f279784469d..dbe7ec1764f858e56cd9c78fb81715d036df1497 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -318,8 +318,10 @@ is_windows_9x (void)
   return s_b_ret;
 }
 
+static Lisp_Object ltime (ULONGLONG);
+
 /* Get total user and system times for get-internal-run-time.
-   Returns a list of three integers if the times are provided by the OS
+   Returns a list of integers if the times are provided by the OS
    (NT derivatives), otherwise it returns the result of current-time. */
 Lisp_Object
 w32_get_internal_run_time (void)
@@ -331,27 +333,13 @@ w32_get_internal_run_time (void)
       if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
         {
           LARGE_INTEGER user_int, kernel_int, total;
-          int microseconds;
+         int time_100ns;
           user_int.LowPart = user.dwLowDateTime;
           user_int.HighPart = user.dwHighDateTime;
           kernel_int.LowPart = kernel.dwLowDateTime;
           kernel_int.HighPart = kernel.dwHighDateTime;
           total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
-          /* FILETIME is 100 nanosecond increments, Emacs only wants
-             microsecond resolution.  */
-          total.QuadPart /= 10;
-          microseconds = total.QuadPart % 1000000;
-          total.QuadPart /= 1000000;
-
-          /* Sanity check to make sure we can represent the result.  */
-          if (total.HighPart == 0)
-            {
-              int secs = total.LowPart;
-
-              return list3 (make_number ((secs >> 16) & 0xffff),
-                            make_number (secs & 0xffff),
-                            make_number (microseconds));
-            }
+         return ltime (total.QuadPart);
         }
     }
 
@@ -4070,15 +4058,17 @@ restore_privilege (TOKEN_PRIVILEGES *priv)
   return ret_val;
 }
 
-static Lisp_Object
-ltime (long time_sec, long time_usec)
+ltime (ULONGLONG time_100ns)
 {
-  return list3 (make_number ((time_sec >> 16) & 0xffff),
+  ULONGLONG time_sec = time_100ns / 10000000;
+  int subsec = time_100ns % 10000000;
+  return list4 (make_number (time_sec >> 16),
                make_number (time_sec & 0xffff),
-               make_number (time_usec));
+               make_number (subsec / 10),
+               make_number (subsec % 10 * 100000));
 }
 
-#define U64_TO_LISP_TIME(time) ltime ((time) / 1000000L, (time) % 1000000L)
+#define U64_TO_LISP_TIME(time) ltime (time)
 
 static int
 process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
@@ -4097,11 +4087,9 @@ process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
   GetSystemTimeAsFileTime (&ft_current);
 
   FILETIME_TO_U64 (tem1, ft_kernel);
-  tem1 /= 10L;
   *stime = U64_TO_LISP_TIME (tem1);
 
   FILETIME_TO_U64 (tem2, ft_user);
-  tem2 /= 10L;
   *utime = U64_TO_LISP_TIME (tem2);
 
   tem3 = tem1 + tem2;
@@ -4110,13 +4098,13 @@ process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
   FILETIME_TO_U64 (tem, ft_creation);
   /* Process no 4 (System) returns zero creation time.  */
   if (tem)
-    tem = (tem - utc_base) / 10L;
+    tem -= utc_base;
   *ctime = U64_TO_LISP_TIME (tem);
 
   if (tem)
     {
       FILETIME_TO_U64 (tem3, ft_current);
-      tem = (tem3 - utc_base) / 10L - tem;
+      tem = (tem3 - utc_base) - tem;
     }
   *etime = U64_TO_LISP_TIME (tem);
 
@@ -6275,7 +6263,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
 {
   int n, sc, err;
   SELECT_TYPE fdset;
-  EMACS_TIME timeout;
+  struct timeval timeout;
   struct Lisp_Process *process = (struct Lisp_Process *)p;
   int fd = process->infd;
 
@@ -6291,7 +6279,8 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
       if (err == EWOULDBLOCK)
         {
           /* Set a small timeout.  */
-          EMACS_SET_SECS_USECS (timeout, 1, 0);
+         timeout.tv_sec = 1;
+         timeout.tv_usec = 0;
           FD_ZERO (&fdset);
           FD_SET ((int)fd, &fdset);
 
index a0739eb55221ae2ae30e119ce625fb8e9ac4b921..0050d64493168ea8de993afd6eaf03fbc7c2f31e 100644 (file)
@@ -29077,18 +29077,20 @@ start_hourglass (void)
 {
 #if defined (HAVE_WINDOW_SYSTEM)
   EMACS_TIME delay;
-  int secs = DEFAULT_HOURGLASS_DELAY, usecs = 0;
 
   cancel_hourglass ();
 
-  if (NUMBERP (Vhourglass_delay))
-    {
-      double duration = extract_float (Vhourglass_delay);
-      if (0 < duration)
-       duration_to_sec_usec (duration, &secs, &usecs);
-    }
+  if (INTEGERP (Vhourglass_delay)
+      && XINT (Vhourglass_delay) > 0)
+    EMACS_SET_SECS_NSECS (delay,
+                         min (XINT (Vhourglass_delay), TYPE_MAXIMUM (time_t)),
+                         0);
+  else if (FLOATP (Vhourglass_delay)
+          && XFLOAT_DATA (Vhourglass_delay) > 0)
+    delay = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (Vhourglass_delay));
+  else
+    EMACS_SET_SECS_NSECS (delay, DEFAULT_HOURGLASS_DELAY, 0);
 
-  EMACS_SET_SECS_USECS (delay, secs, usecs);
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
 #endif
index 9d6a3ba774a8cc1106e0eb80441131ad2a72447f..c7348d2c70aa162df524e237c67dfdfabb881aca 100644 (file)
@@ -34,18 +34,18 @@ static ptrdiff_t gfds_size;
 
 int
 xg_select (int fds_lim, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
-          EMACS_TIME *timeout)
+          EMACS_TIME *timeout, sigset_t *sigmask)
 {
   SELECT_TYPE all_rfds, all_wfds;
   EMACS_TIME tmo, *tmop = timeout;
 
   GMainContext *context;
   int have_wfds = wfds != NULL;
-  int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0, max_fds = fds_lim - 1;
+  int n_gfds = 0, retval = 0, our_fds = 0, max_fds = fds_lim - 1;
   int i, nfds, tmo_in_millisec;
 
   if (!x_in_use)
-    return select (fds_lim, rfds, wfds, efds, timeout);
+    return pselect (fds_lim, rfds, wfds, efds, tmop, sigmask);
 
   if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds));
   else FD_ZERO (&all_rfds);
@@ -90,20 +90,13 @@ xg_select (int fds_lim, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
     {
       EMACS_SET_SECS_USECS (tmo, tmo_in_millisec/1000,
                             1000 * (tmo_in_millisec % 1000));
-      if (!timeout) our_tmo = 1;
-      else
-        {
-          EMACS_TIME difference;
-
-          EMACS_SUB_TIME (difference, tmo, *timeout);
-          if (EMACS_TIME_NEG_P (difference)) our_tmo = 1;
-        }
-
-      if (our_tmo) tmop = &tmo;
+      if (!timeout || EMACS_TIME_LT (tmo, *timeout))
+       tmop = &tmo;
     }
 
   fds_lim = max_fds + 1;
-  nfds = select (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop);
+  nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL,
+                 efds, tmop, sigmask);
 
   if (nfds < 0)
     retval = nfds;
@@ -132,7 +125,7 @@ xg_select (int fds_lim, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
         }
     }
 
-  if (our_fds > 0 || (nfds == 0 && our_tmo))
+  if (our_fds > 0 || (nfds == 0 && tmop == &tmo))
     {
 
       /* If Gtk+ is in use eventually gtk_main_iteration will be called,
index 15d7cd5fdd3d06948dc880cafcc164a98382196b..8e5614ea972854aed0c4dc5d4dd7f2985629df06 100644 (file)
@@ -28,9 +28,9 @@ extern int xg_select (int max_fds,
                       SELECT_TYPE *rfds,
                       SELECT_TYPE *wfds,
                       SELECT_TYPE *efds,
-                      EMACS_TIME *timeout);
+                      EMACS_TIME *timeout,
+                     sigset_t *sigmask);
 
 extern void xgselect_initialize (void);
 
 #endif /* XGSELECT_H */
-
index 08b444f09f2c59c7423f21aece16d66d71cb03c5..16279053e9072bd497e0783770ea9134ea6a617c 100644 (file)
@@ -392,8 +392,6 @@ x_menu_wait_for_event (void *data)
          )
     {
       EMACS_TIME next_time = timer_check (), *ntp;
-      long secs = EMACS_SECS (next_time);
-      long usecs = EMACS_USECS (next_time);
       SELECT_TYPE read_fds;
       struct x_display_info *dpyinfo;
       int n = 0;
@@ -407,7 +405,7 @@ x_menu_wait_for_event (void *data)
           XFlush (dpyinfo->display);
         }
 
-      if (secs < 0 && usecs < 0)
+      if (! EMACS_TIME_VALID_P (next_time))
         ntp = 0;
       else
         ntp = &next_time;
@@ -417,9 +415,9 @@ x_menu_wait_for_event (void *data)
          over an arrow, a timeout scrolls it a bit.  Use xg_select so that
          timeout gets triggered.  */
 
-      xg_select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
+      xg_select (n + 1, &read_fds, NULL, NULL, ntp);
 #else
-      select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
+      pselect (n + 1, &read_fds, NULL, NULL, ntp, NULL);
 #endif
     }
 }
index 49a491d4163181139fdfae6e57a5b4f3ef8b01a2..f21c57b44bb73ac4d32e66cf54a4555f65a4cb0c 100644 (file)
@@ -1139,7 +1139,6 @@ wait_for_property_change_unwind (Lisp_Object loc)
 static void
 wait_for_property_change (struct prop_location *location)
 {
-  int secs, usecs;
   ptrdiff_t count = SPECPDL_INDEX ();
 
   if (property_change_reply_object)
@@ -1156,10 +1155,11 @@ wait_for_property_change (struct prop_location *location)
      property_change_reply, because property_change_reply_object says so.  */
   if (! location->arrived)
     {
-      secs = x_selection_timeout / 1000;
-      usecs = (x_selection_timeout % 1000) * 1000;
-      TRACE2 ("  Waiting %d secs, %d usecs", secs, usecs);
-      wait_reading_process_output (secs, usecs, 0, 0,
+      EMACS_INT timeout = max (0, x_selection_timeout);
+      EMACS_INT secs = timeout / 1000;
+      int nsecs = (timeout % 1000) * 1000000;
+      TRACE2 ("  Waiting %"pI"d secs, %d nsecs", secs, nsecs);
+      wait_reading_process_output (secs, nsecs, 0, 0,
                                   property_change_reply, NULL, 0);
 
       if (NILP (XCAR (property_change_reply)))
@@ -1228,7 +1228,8 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
   Atom type_atom = (CONSP (target_type)
                    ? symbol_to_x_atom (dpyinfo, XCAR (target_type))
                    : symbol_to_x_atom (dpyinfo, target_type));
-  int secs, usecs;
+  EMACS_INT timeout, secs;
+  int nsecs;
 
   if (!FRAME_LIVE_P (f))
     return Qnil;
@@ -1264,10 +1265,11 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
   UNBLOCK_INPUT;
 
   /* This allows quits.  Also, don't wait forever.  */
-  secs = x_selection_timeout / 1000;
-  usecs = (x_selection_timeout % 1000) * 1000;
-  TRACE1 ("  Start waiting %d secs for SelectionNotify", secs);
-  wait_reading_process_output (secs, usecs, 0, 0,
+  timeout = max (0, x_selection_timeout);
+  secs = timeout / 1000;
+  nsecs = (timeout % 1000) * 1000000;
+  TRACE1 ("  Start waiting %"pI"d secs for SelectionNotify", secs);
+  wait_reading_process_output (secs, nsecs, 0, 0,
                               reading_selection_reply, NULL, 0);
   TRACE1 ("  Got event = %d", !NILP (XCAR (reading_selection_reply)));
 
index fec661625f2bd65e163f0f02d018d5389ad83353..cb7aac2838cee7609f6a8229a9912ea67f4145d8 100644 (file)
@@ -85,10 +85,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <X11/Shell.h>
 #endif
 
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
 #include <unistd.h>
 
 #ifdef USE_GTK
@@ -3072,44 +3068,6 @@ x_clear_frame (struct frame *f)
 \f
 /* Invert the middle quarter of the frame for .15 sec.  */
 
-/* We use the select system call to do the waiting, so we have to make
-   sure it's available.  If it isn't, we just won't do visual bells.  */
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-
-
-/* Subtract the `struct timeval' values X and Y, storing the result in
-   *RESULT.  Return 1 if the difference is negative, otherwise 0.  */
-
-static int
-timeval_subtract (struct timeval *result, struct timeval x, struct timeval y)
-{
-  /* Perform the carry for the later subtraction by updating y.  This
-     is safer because on some systems the tv_sec member is unsigned.  */
-  if (x.tv_usec < y.tv_usec)
-    {
-      int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
-      y.tv_usec -= 1000000 * nsec;
-      y.tv_sec += nsec;
-    }
-
-  if (x.tv_usec - y.tv_usec > 1000000)
-    {
-      int nsec = (y.tv_usec - x.tv_usec) / 1000000;
-      y.tv_usec += 1000000 * nsec;
-      y.tv_sec -= nsec;
-    }
-
-  /* Compute the time remaining to wait.  tv_usec is certainly
-     positive.  */
-  result->tv_sec = x.tv_sec - y.tv_sec;
-  result->tv_usec = x.tv_usec - y.tv_usec;
-
-  /* Return indication of whether the result should be considered
-     negative.  */
-  return x.tv_sec < y.tv_sec;
-}
-
 static void
 XTflash (struct frame *f)
 {
@@ -3210,34 +3168,29 @@ XTflash (struct frame *f)
       x_flush (f);
 
       {
-       struct timeval wakeup;
+       EMACS_TIME wakeup, delay;
 
        EMACS_GET_TIME (wakeup);
-
-       /* Compute time to wait until, propagating carry from usecs.  */
-       wakeup.tv_usec += 150000;
-       wakeup.tv_sec += (wakeup.tv_usec / 1000000);
-       wakeup.tv_usec %= 1000000;
+       EMACS_SET_SECS_NSECS (delay, 0, 150 * 1000 * 1000);
+       EMACS_ADD_TIME (wakeup, wakeup, delay);
 
        /* Keep waiting until past the time wakeup or any input gets
           available.  */
        while (! detect_input_pending ())
          {
-           struct timeval current;
-           struct timeval timeout;
+           EMACS_TIME current, timeout;
 
            EMACS_GET_TIME (current);
 
-           /* Break if result would be negative.  */
-           if (timeval_subtract (&current, wakeup, current))
+           /* Break if result would not be positive.  */
+           if (EMACS_TIME_LE (wakeup, current))
              break;
 
            /* How long `select' should wait.  */
-           timeout.tv_sec = 0;
-           timeout.tv_usec = 10000;
+           EMACS_SET_SECS_NSECS (timeout, 0, 10 * 1000 * 1000);
 
            /* Try to wait that long--but we might wake up sooner.  */
-           select (0, NULL, NULL, NULL, &timeout);
+           pselect (0, NULL, NULL, NULL, &timeout, NULL);
          }
       }
 
@@ -3278,8 +3231,6 @@ XTflash (struct frame *f)
   UNBLOCK_INPUT;
 }
 
-#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
-
 
 static void
 XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
@@ -3306,11 +3257,9 @@ XTring_bell (struct frame *f)
 {
   if (FRAME_X_DISPLAY (f))
     {
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
       if (visible_bell)
        XTflash (f);
       else
-#endif
        {
          BLOCK_INPUT;
          XBell (FRAME_X_DISPLAY (f), 0);
@@ -8878,9 +8827,11 @@ x_wait_for_event (struct frame *f, int eventtype)
       FD_SET (fd, &fds);
 
       EMACS_GET_TIME (time_now);
-      EMACS_SUB_TIME (tmo, tmo_at, time_now);
+      if (EMACS_TIME_LT (tmo_at, time_now))
+       break;
 
-      if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
+      EMACS_SUB_TIME (tmo, tmo_at, time_now);
+      if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
         break; /* Timeout */
     }
   pending_event_wait.f = 0;