GNU bug report logs - #9000
patch for higher-resolution time stamps

Previous Next

Package: emacs;

Reported by: Paul Eggert <eggert <at> cs.ucla.edu>

Date: Tue, 5 Jul 2011 06:42:02 UTC

Severity: normal

Tags: patch

Done: Paul Eggert <eggert <at> cs.ucla.edu>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 9000 in the body.
You can then email your comments to 9000 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to owner <at> debbugs.gnu.org, bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Tue, 05 Jul 2011 06:42:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Paul Eggert <eggert <at> cs.ucla.edu>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Tue, 05 Jul 2011 06:42:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-gnu-emacs <at> gnu.org
Subject: patch for higher-resolution time stamps
Date: Mon, 04 Jul 2011 23:40:43 -0700
Currently, Emacs supports time stamps to at most microsecond
resolution, and often to only 1-second resolution, even though most
modern systems have nanosecond-resolution time stamps for clock and
file time stamps.  This leads to some problems, for example:

 * "C-u M-x copy-file RET A RET B" discards the fractional part of A's
   time stamp when copying A to B (except for Windows, which I've been
   told uses special code to preserve the time stamp correctly).

 * The file-attributes function truncates file time stamps to
   one-second resolution, making it impossible for a dired written in
   Emacs to emulate the behavior of "ls --full-time".

 * (format-time-string "%s.%N") is supposed to output
   nanosecond-resolution time stamps, but on the Emacs trunk it always
   outputs a multiple of one microsecond, even when the system clock
   supports nanosecond resolution.

 * If some other process modifies a file during the same second that
   Emacs gets the file's time stamp, Emacs won't notice the conflict,
   as the visited-file-modtime function supports only 1-second
   resolution.  If Emacs used nanosecond-resolution time stamps, this
   race condition would be much less likely.

None of these problems are fatal, but they are annoyances that could
lead to real problems (e.g., when working with "make", which uses
high-resolution file time stamps).

I've proposed a patch for this:

http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00015.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00016.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00017.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00018.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00019.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00020.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00021.html

Stefan asked me in
<http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00069.html>
to make the patch more upward-compatible, by appending a new
picosecond count to the end of the time stamp list, rather than
changing the microsecond to a nanosecond count (which would likely
break more code).  I'll do that soon, but thought I'd first file a bug
report to make this whole issue easier to track.

In part I am also following up to Stefan's suggestion
<http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00217.html>
to have a bug report for this issue.




Information forwarded to owner <at> debbugs.gnu.org, bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Tue, 05 Jul 2011 06:58:01 GMT) Full text and rfc822 format available.

Message #8 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: 9000 <at> debbugs.gnu.org
Subject: More-compatible proposal, using (HIGH LOW USEC PSEC) time stamps
Date: Mon, 04 Jul 2011 23:57:02 -0700
Here's the improved version of the patch that I mentioned.  It follows
Stefan's suggestion in using more-compatible time stamps.  With
this patch, (current-time) returns time stamps in the format
(HIGH LOW USEC PSEC), and existing Lisp code that looks at the 1st
three elements will continue to work as before.  Older-format time
stamps such as (HIGH LOW USEC) are still accepted.

To avoid repetition this patch assumes the already-submitted patches
for the gnulib code, for configure-time support, and for lib-src support:

http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00015.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00018.html
http://lists.gnu.org/archive/html/emacs-devel/2011-07/msg00020.html

as these don't need to be changed to accommodate Stefan's suggestion.

Further suggestions for improvements are welcome.


=== modified file 'etc/ChangeLog'
--- etc/ChangeLog	2011-07-03 21:39:49 +0000
+++ etc/ChangeLog	2011-07-04 08:24:10 +0000
@@ -1,3 +1,7 @@
+2011-07-04  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	* NEWS: Mention addition of picoseconds to time stamp format.
+
 2011-03-29  Kevin Ryde  <user42 <at> zip.com.au>
 
 	* compilation.txt (perl-Test2): New samples.

=== modified file 'etc/NEWS'
--- etc/NEWS	2011-07-02 04:27:41 +0000
+++ etc/NEWS	2011-07-04 08:24:10 +0000
@@ -238,6 +238,13 @@
 *** Tramp offers handlers for file-selinux-context and set-file-selinux-context
 for remote machines which support SELinux.
 
+** 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.
+
 +++
 ** The function format-time-string now supports the %N directive, for
 higher-resolution time stamps.

=== modified file 'doc/lispref/ChangeLog'
--- doc/lispref/ChangeLog	2011-07-03 18:44:53 +0000
+++ doc/lispref/ChangeLog	2011-07-04 08:24:10 +0000
@@ -1,3 +1,10 @@
+2011-07-04  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Document the change to time stamp format and resolution.
+	* os.texi (Time of Day, Time Parsing, Processor Run Time, Idle Timers):
+	* processes.texi (System Processes):
+	Time stamp resolution is now picosecond, not microsecond.
+
 2011-07-03  Tobias C. Rittweiler  <tcr <at> freebits.de>  (tiny change)
 
 	* searching.texi (Match Data): Note that match data can be

=== modified file 'doc/lispref/os.texi'
--- doc/lispref/os.texi	2011-06-03 18:49:33 +0000
+++ doc/lispref/os.texi	2011-07-04 06:42:19 +0000
@@ -1110,8 +1110,8 @@
 instead of the current time.  This argument should have the same form
 as the times obtained from @code{current-time} (see below) and from
 @code{file-attributes} (@pxref{Definition of file-attributes}).  It
-should be a list whose first two elements are integers; a third
-(microsecond) element, if present, is ignored.  @var{time-value} can
+should be a list whose first two elements are integers; trailing
+elements, if present, are ignored.  @var{time-value} can
 also be a cons of two integers, but this usage is obsolete.
 
 @example
@@ -1123,8 +1123,8 @@
 @end defun
 
 @defun current-time
-This function returns the system's time value as a list of three
-integers: @code{(@var{high} @var{low} @var{microsec})}.  The integers
+This function returns the system's time value as a list of four integers:
+@code{(@var{high} @var{low} @var{microsec} @var{picosec})}.  The integers
 @var{high} and @var{low} combine to give the number of seconds since
 0:00 January 1, 1970 UTC (Coordinated Universal Time), which is
 @ifnottex
@@ -1135,10 +1135,14 @@
 @end tex
 
 The third element, @var{microsec}, gives the microseconds since the
-start of the current second (or 0 for systems that return time with
-the resolution of only one second).
+start of the current second.  The fourth element, @var{picosec}, gives
+the picoseconds since the start of the current microsecond.  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.
 
-The first two elements can be compared with file time values such as you
+The list can be compared with file time values such as you
 get with the function @code{file-attributes}.
 @xref{Definition of file-attributes}.
 @end defun
@@ -1340,8 +1344,6 @@
 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
@@ -1493,18 +1495,9 @@
 
 @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
@@ -1748,19 +1741,9 @@
 @c Emacs 19 feature
 @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{high} @var{low}
-@var{microsec})}.  The integers @var{high} and @var{low} combine to
-give the number of seconds of idleness, 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 since the
-start of the current second (or 0 for systems that return time with
-the resolution of only one second).
+been idle, as a list of four integers: @code{(@var{high} @var{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.

=== modified file 'doc/lispref/processes.texi'
--- doc/lispref/processes.texi	2011-06-15 17:30:41 +0000
+++ doc/lispref/processes.texi	2011-07-04 06:42:19 +0000
@@ -1770,7 +1770,7 @@
 @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 @@
 
 @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 @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.

=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog	2011-07-04 16:08:16 +0000
+++ lisp/ChangeLog	2011-07-04 17:40:43 +0000
@@ -1,3 +1,26 @@
+2011-07-04  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Support picosecond-resolution time stamps.
+
+	* 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.
+
+	* lisp/proced.el (proced-time-lessp): Support ps-resolution stamps.
+
 2011-07-04  Stefan Monnier  <monnier <at> iro.umontreal.ca>
 
 	* files.el (find-file): Use pop-to-buffer-same-window (bug#8911).

=== modified file 'lisp/calendar/time-date.el'
--- lisp/calendar/time-date.el	2011-04-19 04:11:01 +0000
+++ lisp/calendar/time-date.el	2011-07-04 07:16:35 +0000
@@ -23,15 +23,15 @@
 
 ;;; 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.
@@ -44,13 +44,15 @@
 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 @@
 	     (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 @@
 	`(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 @@
            (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 @@
 (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)

=== modified file 'lisp/emacs-lisp/timer.el'
--- lisp/emacs-lisp/timer.el	2011-07-04 06:25:23 +0000
+++ lisp/emacs-lisp/timer.el	2011-07-04 08:24:10 +0000
@@ -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)
@@ -42,27 +42,35 @@
             (: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)))
 
 (defsetf 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 @@
 (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 @@
   "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))))))
+  (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)
-  "Advance TIME by SECS seconds and optionally USECS microseconds.
-SECS may be either an integer or a floating point number."
+(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 @@
 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 @@
 	   (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)
@@ -384,7 +399,7 @@
   "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.
 

=== modified file 'lisp/proced.el'
--- lisp/proced.el	2011-06-25 18:08:41 +0000
+++ lisp/proced.el	2011-07-04 07:16:35 +0000
@@ -1170,14 +1170,16 @@
 (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

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2011-07-04 15:32:22 +0000
+++ src/ChangeLog	2011-07-04 17:40:43 +0000
@@ -1,3 +1,171 @@
+2011-07-04  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Add support for picosecond-resolution time stamps.
+	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.c (reset_buffer):
+	* 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.
+
+	* 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.
+
 2011-07-04  Lars Magne Ingebrigtsen  <larsi <at> gnus.org>
 
 	* buffer.c (Foverlay_put): Say what the return value is

=== modified file 'src/Makefile.in'
--- src/Makefile.in	2011-07-01 17:53:59 +0000
+++ src/Makefile.in	2011-07-01 20:41:12 +0000
@@ -147,6 +147,8 @@
 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.
@@ -379,7 +381,7 @@
 ## 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) \

=== modified file 'src/alloc.c'
--- src/alloc.c	2011-06-24 21:25:22 +0000
+++ src/alloc.c	2011-07-01 07:37:04 +0000
@@ -5159,12 +5159,14 @@
     }
 
   /* 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);

=== modified file 'src/atimer.c'
--- src/atimer.c	2011-04-11 06:04:34 +0000
+++ src/atimer.c	2011-07-01 07:37:04 +0000
@@ -26,10 +26,7 @@
 #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 @@
   /* 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 @@
 
       /* 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 @@
 {
   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 @@
 	  t->next = free_atimers;
 	  free_atimers = t;
 	}
-
-      EMACS_GET_TIME (now);
     }
 
   if (! atimers)

=== modified file 'src/buffer.c'
--- src/buffer.c	2011-07-04 15:32:22 +0000
+++ src/buffer.c	2011-07-04 17:40:43 +0000
@@ -714,7 +714,7 @@
   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;
@@ -5850,9 +5850,9 @@
 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.
 

=== modified file 'src/buffer.h'
--- src/buffer.h	2011-06-21 21:32:10 +0000
+++ src/buffer.h	2011-07-04 08:09:05 +0000
@@ -18,7 +18,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 <time.h> /* for time_t */
+#include "systime.h" /* for EMACS_TIME */
 
 /* Accessing the parameters of the current buffer.  */
 
@@ -550,10 +550,13 @@
   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

=== modified file 'src/dired.c'
--- src/dired.c	2011-06-24 21:25:22 +0000
+++ src/dired.c	2011-07-04 08:09:05 +0000
@@ -62,6 +62,7 @@
 #endif /* HAVE_DIRENT_H */
 
 #include <filemode.h>
+#include <stat-time.h>
 
 #ifdef MSDOS
 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
@@ -889,8 +890,8 @@
  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.
@@ -975,9 +976,9 @@
   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

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2011-06-22 18:15:23 +0000
+++ src/dispextern.h	2011-07-01 07:37:04 +0000
@@ -68,6 +68,10 @@
 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)
@@ -2719,7 +2723,7 @@
 {
   /* 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;

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2011-06-25 18:21:00 +0000
+++ src/dispnew.c	2011-07-01 07:37:04 +0000
@@ -169,24 +169,11 @@
 static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
 
 
-/* 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.  */
 
@@ -3227,14 +3214,12 @@
 
   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 ())
 	{
@@ -3242,14 +3227,10 @@
 	  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))
     {
@@ -3333,9 +3314,7 @@
 #endif
     }
 
-#if PERIODIC_PREEMPTION_CHECKING
  do_pause:
-#endif
   /* Reset flags indicating that a window should be updated.  */
   set_window_update_flags (root_window, 0);
 
@@ -3388,23 +3367,17 @@
 
       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);
@@ -3649,10 +3622,9 @@
 #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 ())
@@ -4680,10 +4652,9 @@
 #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 ())
@@ -5890,46 +5861,24 @@
        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;
-
-  if (NILP (milliseconds))
-    XSETINT (milliseconds, 0);
-  else
-    CHECK_NUMBER (milliseconds);
-  usec = XINT (milliseconds) * 1000;
-
-  {
-    double duration = extract_float (seconds);
-    sec = (int) duration;
-    usec += (duration - sec) * 1000000;
-  }
-
-#ifndef EMACS_HAS_USECS
-  if (sec == 0 && usec != 0)
-    error ("Millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
-#endif
-
-  /* Assure that 0 <= usec < 1000000.  */
-  if (usec < 0)
-    {
-      /* We can't rely on the rounding being correct if usec is negative.  */
-      if (-1000000 < usec)
-	sec--, usec += 1000000;
-      else
-	sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
-    }
-  else
-    sec += usec / 1000000, usec %= 1000000;
-
-  if (sec < 0 || (sec == 0 && usec == 0))
-    return Qnil;
-
-  wait_reading_process_output (sec, usec, 0, 0, Qnil, NULL, 0);
+  double duration = extract_float (seconds);
+
+  if (!NILP (milliseconds))
+    {
+      CHECK_NUMBER (milliseconds);
+      duration += XINT (milliseconds) / 1000.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;
 }
@@ -5948,7 +5897,9 @@
 Lisp_Object
 sit_for (Lisp_Object timeout, int reading, int do_display)
 {
-  int sec, usec;
+  EMACS_TIME t;
+  intmax_t sec;
+  int nsec;
 
   swallow_events (do_display);
 
@@ -5962,30 +5913,36 @@
   if (INTEGERP (timeout))
     {
       sec = XINT (timeout);
-      usec = 0;
+      if (! (0 < sec))
+	return Qt;
+      nsec = 0;
     }
   else if (FLOATP (timeout))
     {
       double seconds = XFLOAT_DATA (timeout);
-      sec = (int) seconds;
-      usec = (int) ((seconds - sec) * 1000000);
+      if (! (0 < seconds))
+	return Qt;
+      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;
-      usec = 0;
+      nsec = 0;
     }
   else
     wrong_type_argument (Qnumberp, timeout);
 
-  if (sec == 0 && usec == 0 && !EQ (timeout, Qt))
-    return Qt;
 
 #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;

=== modified file 'src/editfns.c'
--- src/editfns.c	2011-07-04 07:44:38 +0000
+++ src/editfns.c	2011-07-04 08:24:10 +0000
@@ -84,7 +84,6 @@
 extern Lisp_Object w32_get_internal_run_time (void);
 #endif
 
-static void time_overflow (void) NO_RETURN;
 static int tm_diff (struct tm *, struct tm *);
 static void update_buffer_properties (EMACS_INT, EMACS_INT);
 
@@ -1402,14 +1401,13 @@
 #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)
 {
@@ -1437,40 +1435,33 @@
 
 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?  */
@@ -1484,10 +1475,8 @@
       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 ();
@@ -1498,101 +1487,175 @@
 }
 
 
-/* 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.  */
-int
-lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec)
+static int
+disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
+		       Lisp_Object *plow, Lisp_Object *pusec,
+		       Lisp_Object *ppsec)
 {
-  if (NILP (specified_time))
-    {
-      if (usec)
-        {
-          EMACS_TIME t;
-
-          EMACS_GET_TIME (t);
-          *usec = EMACS_USECS (t);
-          *result = EMACS_SECS (t);
-          return 1;
-        }
-      else
-        return time (result) != -1;
-    }
-  else
-    {
-      Lisp_Object high, low;
-      EMACS_INT hi;
-      high = Fcar (specified_time);
-      CHECK_NUMBER (high);
-      low = Fcdr (specified_time);
+  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))
-        {
-          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);
-                  *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);
+	{
+	  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
+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
+    {
+      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, 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);
+    }
+}
+
 
 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
@@ -1647,7 +1710,7 @@
 
 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
@@ -1699,19 +1762,15 @@
 For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".  */)
   (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
 {
-  time_t value;
+  EMACS_TIME t;
   ptrdiff_t size;
-  int usec;
   int ns;
   struct tm *tm;
   int ut = ! NILP (universal);
 
   CHECK_STRING (format_string);
 
-  if (! (lisp_time_argument (timeval, &value, &usec)
-	 && 0 <= usec && usec < 1000000))
-    error ("Invalid time specification");
-  ns = usec * 1000;
+  t = lisp_time_argument (timeval, 0);
 
   format_string = code_convert_string_norecord (format_string,
 						Vlocale_coding_system, 1);
@@ -1722,7 +1781,7 @@
     size = size * 6 + 50;
 
   BLOCK_INPUT;
-  tm = ut ? gmtime (&value) : localtime (&value);
+  tm = ut ? gmtime (EMACS_SECS_ADDR (t)) : localtime (EMACS_SECS_ADDR (t));
   UNBLOCK_INPUT;
   if (! tm)
     time_overflow ();
@@ -1738,7 +1797,7 @@
       BLOCK_INPUT;
       result = emacs_nmemftime (buf, size, SSDATA (format_string),
 				SBYTES (format_string),
-				tm, ut, ns);
+				tm, ut, EMACS_NSECS (t));
       UNBLOCK_INPUT;
       if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
 	return code_convert_string_norecord (make_unibyte_string (buf, result),
@@ -1749,7 +1808,7 @@
       result = emacs_nmemftime (NULL, (size_t) -1,
 				SSDATA (format_string),
 				SBYTES (format_string),
-				tm, ut, ns);
+				tm, ut, EMACS_NSECS (t));
       UNBLOCK_INPUT;
       if (STRING_BYTES_BOUND <= result)
 	string_overflow ();
@@ -1774,14 +1833,11 @@
 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);
   UNBLOCK_INPUT;
@@ -1929,13 +1985,10 @@
 but this is considered obsolete.  */)
   (Lisp_Object specified_time)
 {
-  time_t value;
+  time_t value = lisp_seconds_argument (specified_time);
   struct tm *tm;
   register char *tem;
 
-  if (! lisp_time_argument (specified_time, &value, NULL))
-    error ("Invalid time specification");
-
   /* Convert to a string, checking for out-of-range time stamps.
      Don't use 'ctime', as that might dump core if VALUE is out of
      range.  */
@@ -1991,23 +2044,18 @@
 the data it can't find.  */)
   (Lisp_Object specified_time)
 {
-  time_t value;
+  time_t value = lisp_seconds_argument (specified_time);
   struct tm *t;
   struct tm gmt;
 
-  if (!lisp_time_argument (specified_time, &value, NULL))
-    t = NULL;
-  else
+  BLOCK_INPUT;
+  t = gmtime (&value);
+  if (t)
     {
-      BLOCK_INPUT;
-      t = gmtime (&value);
-      if (t)
-	{
-	  gmt = *t;
-	  t = localtime (&value);
-	}
-      UNBLOCK_INPUT;
+      gmt = *t;
+      t = localtime (&value);
     }
+  UNBLOCK_INPUT;
 
   if (t)
     {

=== modified file 'src/fileio.c'
--- src/fileio.c	2011-07-04 14:34:31 +0000
+++ src/fileio.c	2011-07-04 17:40:43 +0000
@@ -76,6 +76,7 @@
 #endif
 
 #include "systime.h"
+#include <stat-time.h>
 
 #ifdef HPUX
 #include <netio.h>
@@ -1877,7 +1878,7 @@
       /* 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);
@@ -1978,24 +1979,21 @@
     }
 #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
@@ -2936,11 +2934,7 @@
 {
   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));
 
@@ -2953,12 +2947,7 @@
   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;
@@ -4059,7 +4048,7 @@
 
       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;
 	}
@@ -4224,7 +4213,7 @@
     }
 
   if (!NILP (visit)
-      && current_buffer->modtime == -1)
+      && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
     {
       /* If visiting nonexistent file, return nil.  */
       report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
@@ -4659,7 +4648,7 @@
      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;
     }
 
@@ -4936,6 +4925,7 @@
   struct stat st;
   Lisp_Object handler;
   Lisp_Object filename;
+  EMACS_TIME mtime, diff, one_second;
 
   if (NILP (buf))
     b = current_buffer;
@@ -4946,7 +4936,7 @@
     }
 
   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.  */
@@ -4957,20 +4947,25 @@
 
   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;
@@ -4983,7 +4978,7 @@
 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;
 }
@@ -4991,15 +4986,15 @@
 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
+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.
 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,
@@ -5009,12 +5004,12 @@
 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
@@ -5036,7 +5031,7 @@
 
       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;
         }
     }

=== modified file 'src/gtkutil.c'
--- src/gtkutil.c	2011-06-26 18:47:07 +0000
+++ src/gtkutil.c	2011-07-01 07:37:04 +0000
@@ -1579,16 +1579,16 @@
 {
   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;
 }

=== modified file 'src/image.c'
--- src/image.c	2011-06-23 00:46:41 +0000
+++ src/image.c	2011-07-01 07:37:04 +0000
@@ -1076,11 +1076,8 @@
 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.  */
@@ -1524,9 +1521,9 @@
       else if (INTEGERP (Vimage_cache_eviction_delay))
 	{
 	  /* Free cache based on timestamp.  */
-	  EMACS_TIME t;
-	  time_t old;
-	  int delay, nimages = 0;
+	  EMACS_TIME old, t;
+	  double delay;
+	  unsigned nimages = 0;
 
 	  for (i = 0; i < c->used; ++i)
 	    if (c->images[i])
@@ -1534,17 +1531,18 @@
 
 	  /* If the number of cached images has grown unusually large,
 	     decrease the cache eviction delay (Bug#6230).  */
-	  delay = XFASTINT (Vimage_cache_eviction_delay);
+	  delay = XINT (Vimage_cache_eviction_delay);
 	  if (nimages > 40)
-	    delay = max (1, 1600 * delay / (nimages*nimages));
+	    delay = 1600 * delay / nimages / nimages;
+	  delay = max (1, delay);
 
 	  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;
@@ -1717,7 +1715,6 @@
 {
   struct image *img;
   EMACS_UINT hash;
-  EMACS_TIME now;
 
   /* F must be a window-system frame, and SPEC must be a valid image
      specification.  */
@@ -1812,8 +1809,7 @@
     }
 
   /* 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;

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2011-07-02 23:40:04 +0000
+++ src/keyboard.c	2011-07-04 08:24:10 +0000
@@ -2014,12 +2014,13 @@
       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);
 	}
@@ -2087,7 +2088,7 @@
 bind_polling_period (int n)
 {
 #ifdef POLL_FOR_INPUT
-  int new = polling_period;
+  EMACS_INT new = polling_period;
 
   if (n > new)
     new = n;
@@ -2217,7 +2218,7 @@
 /* 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;
@@ -2268,7 +2269,7 @@
 
 Lisp_Object
 read_char (int commandflag, int 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;
   int jmpcount;
@@ -3769,7 +3770,7 @@
 static Lisp_Object
 kbd_buffer_get_event (KBOARD **kbp,
                       int *used_mouse_menu,
-                      struct timeval *end_time)
+                      EMACS_TIME *end_time)
 {
   register int c;
   Lisp_Object obj;
@@ -3842,8 +3843,9 @@
 	  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);
 	    }
 	}
@@ -4205,7 +4207,7 @@
   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);
@@ -4219,7 +4221,7 @@
 
       timer = XCAR (timers);
 
-      if (!VECTORP (timer) || ASIZE (timer) != 8)
+      if (!VECTORP (timer) || ASIZE (timer) != 9)
 	continue;
       XVECTOR (timer)->contents[0] = Qnil;
     }
@@ -4230,7 +4232,7 @@
 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.  */
@@ -4238,7 +4240,7 @@
 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;
@@ -4252,6 +4254,24 @@
    ...).  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.
@@ -4269,17 +4289,16 @@
 {
   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;
@@ -4297,8 +4316,10 @@
   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))
@@ -4307,113 +4328,84 @@
       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});
-
-      /* Skip past invalid timers and timers already handled.  */
-      if (CONSP (timers))
-	{
-	  timer = XCAR (timers);
-	  if (!VECTORP (timer) || ASIZE (timer) != 8)
-	    {
-	      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;
-	    }
-	}
-      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_timers = XCDR (idle_timers);
-	      continue;
-	    }
-	}
-
-      /* Set TIMER, TIMER_TIME and TIMER_DIFFERENCE
+      EMACS_TIME timer_difference, idle_timer_difference;
+      int ripe, timer_ripe = 0, idle_timer_ripe = 0;
+
+      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).  */
+	 this timer becomes ripe (negative if it's already ripe).
+         Skip past invalid timers and timers already handled.  */
       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);
+	  if (! decode_timer (timer, &timer_time))
+	    {
+	      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);
 	}
 
-      /* Set IDLE_TIMER, IDLE_TIMER_TIME and IDLE_TIMER_DIFFERENCE
+      /* Likewise for IDLE_TIMER 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);
+	  if (! decode_timer (idle_timer, &idle_timer_time))
+	    {
+	      idle_timers = XCDR (idle_timers);
+	      continue;
+	    }
+
+	  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]))
 	    {
 	      int count = SPECPDL_INDEX ();
@@ -4460,7 +4452,7 @@
    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.  */
 
@@ -4473,33 +4465,29 @@
     {
       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;
@@ -10790,7 +10778,7 @@
 }
 
 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;
 
@@ -11393,7 +11381,7 @@
   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;

=== modified file 'src/lisp.h'
--- src/lisp.h	2011-06-24 21:25:22 +0000
+++ src/lisp.h	2011-07-01 07:37:04 +0000
@@ -3011,6 +3011,7 @@
 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 EMACS_INT clip_to_bounds (EMACS_INT, EMACS_INT, EMACS_INT);
@@ -3307,7 +3308,7 @@
 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);

=== modified file 'src/lread.c'
--- src/lread.c	2011-07-02 16:18:24 +0000
+++ src/lread.c	2011-07-04 08:24:10 +0000
@@ -604,14 +604,10 @@
   /* Compute timeout.  */
   if (NUMBERP (seconds))
     {
-      EMACS_TIME wait_time;
-      int sec, usec;
       double duration = extract_float (seconds);
+      EMACS_TIME wait_time = EMACS_TIME_FROM_DOUBLE (duration);
 
-      sec  = (int) duration;
-      usec = (duration - sec) * 1000000;
       EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (wait_time, sec, usec);
       EMACS_ADD_TIME (end_time, end_time, wait_time);
     }
 

=== modified file 'src/msdos.c'
--- src/msdos.c	2011-06-24 21:25:22 +0000
+++ src/msdos.c	2011-07-01 07:37:04 +0000
@@ -4072,13 +4072,6 @@
 #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.
@@ -4147,12 +4140,12 @@
 
 	  /* 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 ();

=== modified file 'src/nsterm.h'
--- src/nsterm.h	2011-06-22 06:16:16 +0000
+++ src/nsterm.h	2011-07-01 07:37:04 +0000
@@ -787,7 +787,8 @@
 
 /* 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;

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2011-05-28 16:56:53 +0000
+++ src/nsterm.m	2011-07-01 07:37:04 +0000
@@ -180,7 +180,6 @@
 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;
@@ -383,67 +382,30 @@
     }
 }
 
-
-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);
     }
 }
 
@@ -3318,7 +3280,7 @@
 
 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
    -------------------------------------------------------------------------- */
@@ -3326,12 +3288,14 @@
   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 */
@@ -3344,8 +3308,9 @@
     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;
 
@@ -3354,7 +3319,7 @@
 
     /* 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:)
@@ -3362,7 +3327,7 @@
                                           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:)
@@ -3404,7 +3369,7 @@
         }
       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;
@@ -4367,6 +4332,7 @@
    -------------------------------------------------------------------------- */
 {
   int result;
+  struct timespec select_timeout;
   /* NSTRACE (fd_handler); */
 
   if (select_nfds == 0)
@@ -4374,9 +4340,8 @@
 
   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));

=== modified file 'src/process.c'
--- src/process.c	2011-07-01 09:18:46 +0000
+++ src/process.c	2011-07-04 08:09:05 +0000
@@ -210,13 +210,11 @@
 #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)
 
@@ -3264,7 +3262,7 @@
 	{
 	  /* 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;
@@ -3272,8 +3270,7 @@
 	  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)
@@ -3875,7 +3872,8 @@
 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, usecs = 0;
+  intmax_t secs;
+  int nsecs;
 
   if (! NILP (process))
     CHECK_PROCESS (process);
@@ -3894,27 +3892,36 @@
 	}
     }
 
+  secs = 0;
+  nsecs = -1;
+
   if (!NILP (seconds))
     {
       if (INTEGERP (seconds))
-	secs = XINT (seconds);
+	{
+	  if (0 < XINT (seconds))
+	    {
+	      secs = XINT (seconds);
+	      nsecs = 0;
+	    }
+	}
       else if (FLOATP (seconds))
 	{
-	  double timeout = XFLOAT_DATA (seconds);
-	  secs = (int) timeout;
-	  usecs = (int) ((timeout - (double) secs) * 1000000);
+	  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);
-
-      if (secs < 0 || (secs == 0 && usecs == 0))
-	secs = -1, usecs = 0;
     }
-  else
-    secs = NILP (process) ? -1 : 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 :
@@ -4155,34 +4162,19 @@
 {
 }
 
-/* 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
@@ -4209,7 +4201,7 @@
    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)
@@ -4229,7 +4221,7 @@
   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!!");
 
@@ -4241,12 +4233,20 @@
 			 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);
     }
 
@@ -4270,7 +4270,7 @@
 
       /* 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
@@ -4278,12 +4278,12 @@
 
 	  EMACS_SET_SECS_USECS (timeout, 0, 0);
 	}
-      else if (time_limit || microsecs)
+      else if (time_limit || nsecs)
 	{
 	  EMACS_GET_TIME (timeout);
+	  if (EMACS_TIME_LE (end_time, timeout))
+	    break;
 	  EMACS_SUB_TIME (timeout, end_time, timeout);
-	  if (EMACS_TIME_NEG_P (timeout))
-	    break;
 	}
       else
 	{
@@ -4329,21 +4329,22 @@
 	      && requeued_events_pending_p ())
 	    break;
 
-	  if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
-	    {
-	      EMACS_TIME difference;
-	      EMACS_SUB_TIME (difference, timer_delay, timeout);
-	      if (EMACS_TIME_NEG_P (difference))
-		{
-		  timeout = timer_delay;
-		  timeout_reduced_for_timers = 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 ();
+	  /* If time_limit is negative, we are not going to wait at all.  */
+	  if (0 <= nsecs)
+	    {
+	      if (EMACS_TIME_VALID_P (timer_delay))
+		{
+		  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 ();
+		}
 	    }
 	}
 
@@ -4372,14 +4373,14 @@
 	  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
@@ -4502,9 +4503,9 @@
 	     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];
@@ -4519,11 +4520,11 @@
 			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
@@ -4532,12 +4533,12 @@
 #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
@@ -4564,7 +4565,7 @@
       /*  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)
@@ -4716,7 +4717,7 @@
 	      if (wait_channel == channel)
 		{
 		  wait_channel = -1;
-		  time_limit = -1;
+		  nsecs = -1;
 		  got_some_input = 1;
 		}
 	      proc = chan_process[channel];
@@ -5488,12 +5489,8 @@
 		      else if (STRINGP (object))
 			offset = buf - SSDATA (object);
 
-#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);
 		      if (BUFFERP (object))
 			buf = (char *) BUF_BYTE_ADDRESS (XBUFFER (object),
 							 offset);
@@ -6647,9 +6644,15 @@
    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
@@ -6666,7 +6669,7 @@
    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)
@@ -6676,11 +6679,19 @@
   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);
     }
 
@@ -6706,7 +6717,7 @@
 
       /* 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
@@ -6714,12 +6725,12 @@
 
 	  EMACS_SET_SECS_USECS (timeout, 0, 0);
 	}
-      else if (time_limit || microsecs)
+      else if (time_limit || nsecs)
 	{
 	  EMACS_GET_TIME (timeout);
+	  if (EMACS_TIME_LE (end_time, timeout))
+	    break;
 	  EMACS_SUB_TIME (timeout, end_time, timeout);
-	  if (EMACS_TIME_NEG_P (timeout))
-	    break;
 	}
       else
 	{
@@ -6752,11 +6763,9 @@
 	      && 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;
@@ -6792,8 +6801,7 @@
 	  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;
 
@@ -6803,7 +6811,7 @@
       /*  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;
 
@@ -7106,19 +7114,20 @@
  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)

=== modified file 'src/process.h'
--- src/process.h	2011-05-12 07:07:06 +0000
+++ src/process.h	2011-07-01 07:37:04 +0000
@@ -104,8 +104,8 @@
        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'.

=== modified file 'src/sysdep.c'
--- src/sysdep.c	2011-06-25 08:40:38 +0000
+++ src/sysdep.c	2011-07-01 07:37:04 +0000
@@ -34,6 +34,7 @@
 #include <allocator.h>
 #include <careadlinkat.h>
 #include <ignore-value.h>
+#include <utimens.h>
 
 #include "lisp.h"
 #include "sysselect.h"
@@ -103,20 +104,6 @@
 
 #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);
@@ -2013,30 +2000,6 @@
 #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)
  */
 
@@ -2072,20 +2035,43 @@
 #endif /* HAVE_DIRENT_H */
 
 
+/* Return a struct timeval that is roughly equivalent to T.
+   Use the least timeval not less than T.
+   Return an extremal value if the result would overflow.  */
+struct timeval
+make_timeval (EMACS_TIME t)
+{
+  struct timeval tv;
+  tv.tv_sec = t.tv_sec;
+  tv.tv_usec = t.tv_nsec / 1000;
+
+  if (t.tv_nsec % 1000 != 0)
+    {
+      if (tv.tv_usec < 999999)
+	tv.tv_usec++;
+      else if (tv.tv_sec < TYPE_MAXIMUM (time_t))
+	{
+	  tv.tv_sec++;
+	  tv.tv_usec = 0;
+	}
+    }
+
+  return tv;
+}
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+   ATIME and MTIME, respectively.
+   FD must be either negative -- in which case it is ignored --
+   or a file descriptor that is open on FILE.
+   If FD is nonnegative, then FILE can be NULL.  */
 int
-set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
+set_file_times (int fd, 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 */
+  struct timespec timespec[2];
+  timespec[0] = atime;
+  timespec[1] = mtime;
+  return fdutimens (fd, filename, timespec);
 }
 
 /* mkdir and rmdir functions, for systems which don't have them.  */
@@ -2549,60 +2535,82 @@
 #endif /* !defined (WINDOWSNT) */
 
 #ifdef GNU_LINUX
-static void
-time_from_jiffies (unsigned long long tval, long hz,
-		   time_t *sec, unsigned *usec)
+static EMACS_TIME
+time_from_jiffies (unsigned long long tval, long hz)
 {
-  unsigned long long ullsec;
+  unsigned long long s = tval / hz;
+  unsigned long long frac = tval % hz;
+  int ns;
+  EMACS_TIME t;
 
-  *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;
+  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)
@@ -2701,7 +2709,7 @@
   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;
@@ -2828,35 +2836,18 @@
 	  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);
@@ -3037,27 +3028,13 @@
 		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.tv_sec)), 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);
 

=== modified file 'src/sysselect.h'
--- src/sysselect.h	2011-01-25 04:08:28 +0000
+++ src/sysselect.h	2011-07-01 07:37:04 +0000
@@ -16,7 +16,6 @@
 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 @@
 #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 @@
 #if !defined (HAVE_SELECT)
 #define select sys_select
 #endif
-

=== modified file 'src/systime.h'
--- src/systime.h	2011-05-20 06:37:13 +0000
+++ src/systime.h	2011-07-04 08:09:05 +0000
@@ -19,16 +19,7 @@
 #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
@@ -59,91 +50,64 @@
 #endif
 #endif
 
-/* 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.
-
-   EMACS_SECS (TIME) is an rvalue for the seconds component of TIME.
+/* 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
+
+/* 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_ADDR_SECS (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_SET_SECS_USECS (TIME, SECS, USECS) sets both components of TIME.
-
-   EMACS_GET_TIME (TIME) stores the current system time in TIME, which
-	should be an lvalue.
-
-   EMACS_ADD_TIME (DEST, SRC1, SRC2) adds SRC1 to SRC2 and stores the
-	result in DEST.  SRC should not be negative.
-
-   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.
-
-*/
-
-#ifdef HAVE_TIMEVAL
-
-#define EMACS_HAS_USECS
-
-#define EMACS_TIME struct timeval
+   EMACS_NSECS (TIME) is an rvalue for the nanoseconds component of TIME.
+   EMACS_SET_NSECS (TIME, NANOSECONDS) sets that to NANOSECONDS.
+
+   EMACS_SET_SECS_NSECS (TIME, SECS, NSECS) sets both components of TIME.  */
 #define EMACS_SECS(time)		    ((time).tv_sec  + 0)
-#define EMACS_USECS(time)		    ((time).tv_usec + 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_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) */
-
+#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)))
+
+/* 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))
 
-extern int set_file_times (const char *, EMACS_TIME, EMACS_TIME);
+/* Set TIME to an invalid time stamp.  */
+#define EMACS_SET_INVALID_TIME(time)	    EMACS_SET_SECS_NSECS(time, 0, -1)
+
+/* 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))
+
+/* Return the sign of the valid time stamp TIME, either -1, 0, or 1.  */
+#define EMACS_TIME_SIGN(time)		timespec_sign (time)
+
+/* Return 1 if TIME is a valid time stamp.  */
+#define EMACS_TIME_VALID_P(time)	(0 <= (time).tv_nsec)
+
+/* 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)
+
+/* Convert the Emacs time T to an approximate double value D.  */
+#define EMACS_TIME_TO_DOUBLE(t)		timespectod (t)
+
+/* 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 *);
@@ -152,29 +116,20 @@
    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 */

=== modified file 'src/term.c'
--- src/term.c	2011-05-18 00:39:40 +0000
+++ src/term.c	2011-07-01 07:37:04 +0000
@@ -24,6 +24,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <sys/file.h>
+#include <sys/time.h>
 #include <unistd.h>
 #include <signal.h>
 #include <setjmp.h>
@@ -2683,6 +2684,18 @@
   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
@@ -2702,7 +2715,6 @@
 		     Lisp_Object *y, Time *timeptr)
 {
   struct timeval now;
-  Time sec, usec;
 
   *fp = SELECTED_FRAME ();
   (*fp)->mouse_moved = 0;
@@ -2713,9 +2725,7 @@
   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.
@@ -2739,7 +2749,7 @@
       }
     }
   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;

=== modified file 'src/undo.c'
--- src/undo.c	2011-06-24 21:25:22 +0000
+++ src/undo.c	2011-07-04 08:09:05 +0000
@@ -225,7 +225,7 @@
     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));
 }
 
@@ -497,10 +497,23 @@
 	      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;
@@ -508,7 +521,7 @@
 		  /* 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 ();

=== modified file 'src/w32.c'
--- src/w32.c	2011-06-24 21:25:22 +0000
+++ src/w32.c	2011-07-04 08:09:05 +0000
@@ -316,8 +316,10 @@
   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)
@@ -329,27 +331,13 @@
       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);
         }
     }
 
@@ -4004,15 +3992,17 @@
   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,
@@ -4031,11 +4021,9 @@
   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;
@@ -4044,13 +4032,13 @@
   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);
 
@@ -6198,7 +6186,7 @@
 {
   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;
 
@@ -6214,7 +6202,8 @@
       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);
 

=== modified file 'src/xdisp.c'
--- src/xdisp.c	2011-06-24 21:25:22 +0000
+++ src/xdisp.c	2011-07-01 07:37:04 +0000
@@ -27098,25 +27098,20 @@
 {
 #if defined (HAVE_WINDOW_SYSTEM)
   EMACS_TIME delay;
-  int secs, usecs = 0;
 
   cancel_hourglass ();
 
   if (INTEGERP (Vhourglass_delay)
       && XINT (Vhourglass_delay) > 0)
-    secs = XFASTINT (Vhourglass_delay);
+    EMACS_SET_SECS_NSECS (delay,
+			  min (XINT (Vhourglass_delay), TYPE_MAXIMUM (time_t)),
+			  0);
   else if (FLOATP (Vhourglass_delay)
 	   && XFLOAT_DATA (Vhourglass_delay) > 0)
-    {
-      Lisp_Object tem;
-      tem = Ftruncate (Vhourglass_delay, Qnil);
-      secs = XFASTINT (tem);
-      usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
-    }
+    delay = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (Vhourglass_delay));
   else
-    secs = DEFAULT_HOURGLASS_DELAY;
+    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

=== modified file 'src/xgselect.c'
--- src/xgselect.c	2011-07-01 09:18:46 +0000
+++ src/xgselect.c	2011-07-01 20:41:12 +0000
@@ -33,14 +33,14 @@
 
 int
 xg_select (int max_fds, 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 = g_main_context_default ();
   int have_wfds = wfds != NULL;
-  int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0;
+  int n_gfds = 0, retval = 0, our_fds = 0;
   int i, nfds, tmo_in_millisec;
 
   if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds));
@@ -86,20 +86,12 @@
     {
       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;
     }
 
-  nfds = select (max_fds+1, &all_rfds, have_wfds ? &all_wfds : NULL,
-                 efds, tmop);
+  nfds = pselect (max_fds+1, &all_rfds, have_wfds ? &all_wfds : NULL,
+		  efds, tmop, sigmask);
 
   if (nfds < 0)
     retval = nfds;
@@ -128,7 +120,7 @@
         }
     }
 
-  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,

=== modified file 'src/xgselect.h'
--- src/xgselect.h	2011-01-26 08:36:39 +0000
+++ src/xgselect.h	2011-07-01 07:37:04 +0000
@@ -28,9 +28,9 @@
                       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 */
-

=== modified file 'src/xmenu.c'
--- src/xmenu.c	2011-06-24 21:25:22 +0000
+++ src/xmenu.c	2011-07-01 07:37:04 +0000
@@ -388,8 +388,6 @@
          )
     {
       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;
@@ -403,12 +401,12 @@
           XFlush (dpyinfo->display);
         }
 
-      if (secs < 0 && usecs < 0)
+      if (! EMACS_TIME_VALID_P (next_time))
         ntp = 0;
       else
         ntp = &next_time;
 
-      select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
+      pselect (n + 1, &read_fds, NULL, NULL, ntp, NULL);
     }
 }
 #endif /* ! MSDOS */

=== modified file 'src/xselect.c'
--- src/xselect.c	2011-06-21 02:16:54 +0000
+++ src/xselect.c	2011-07-01 07:37:04 +0000
@@ -1118,7 +1118,6 @@
 static void
 wait_for_property_change (struct prop_location *location)
 {
-  int secs, usecs;
   int count = SPECPDL_INDEX ();
 
   if (property_change_reply_object)
@@ -1135,10 +1134,11 @@
      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)))
@@ -1207,7 +1207,8 @@
   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;
@@ -1243,10 +1244,11 @@
   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)));
 

=== modified file 'src/xterm.c'
--- src/xterm.c	2011-06-24 21:25:22 +0000
+++ src/xterm.c	2011-07-01 07:37:04 +0000
@@ -85,10 +85,6 @@
 #include <X11/Shell.h>
 #endif
 
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
 #include <unistd.h>
 
 #ifdef USE_GTK
@@ -2949,44 +2945,6 @@
 
 /* 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)
 {
@@ -3087,34 +3045,29 @@
       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);
 	  }
       }
 
@@ -3155,8 +3108,6 @@
   UNBLOCK_INPUT;
 }
 
-#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
-
 
 static void
 XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
@@ -3183,11 +3134,9 @@
 {
   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);
@@ -8713,9 +8662,11 @@
       FD_SET (fd, &fds);
 
       EMACS_GET_TIME (time_now);
+      if (EMACS_TIME_LT (tmo_at, time_now))
+	break;
+
       EMACS_SUB_TIME (tmo, tmo_at, time_now);
-
-      if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
+      if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
         break; /* Timeout */
     }
   pending_event_wait.f = 0;




Information forwarded to owner <at> debbugs.gnu.org, bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Wed, 06 Jul 2011 17:01:02 GMT) Full text and rfc822 format available.

Message #11 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: 9000 <at> debbugs.gnu.org
Cc: Eli Zaretskii <eliz <at> gnu.org>
Subject: Update time patch for Frandom, pthread_sigmask, etc.
Date: Wed, 06 Jul 2011 10:00:13 -0700
Here are three minor updates to the previous patch for high-resolution
time stamps, to accommodate recent changes to Emacs and to gnulib.
Almost all of this is automatically generated.  I don't think this
affects the Windows build (although the last patch builds a wrapper
for signal.h, to support pthread_sigmask, this is irrelevant for
Windows), but I'm sending this as a heads-up, just in case.


* fns.c (Frandom): Use nanoseconds, not microseconds, for seed.
=== modified file 'src/fns.c'
--- src/fns.c	2011-07-05 02:51:15 +0000
+++ src/fns.c	2011-07-06 16:32:00 +0000
@@ -84,7 +84,7 @@
     {
       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)

==============================================================================

* Makefile.in (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.
=== modified file 'Makefile.in'
--- Makefile.in	2011-07-01 06:21:22 +0000
+++ Makefile.in	2011-07-06 16:24:49 +0000
@@ -340,6 +340,7 @@
   symlink sys_stat sys_time \
   time timespec-add timespec-sub utimens
 GNULIB_TOOL_FLAGS = \
+ --avoid=select --avoid=sigprocmask \
  --conditional-dependencies --import --no-changelog --no-vc-files \
  --makefile-name=gnulib.mk
 sync-from-gnulib: $(gnulib_srcdir)

==============================================================================

=== modified file '.bzrignore'
--- .bzrignore	2011-06-27 04:31:43 +0000
+++ .bzrignore	2011-07-06 16:49:44 +0000
@@ -52,6 +52,7 @@
 lib/c++defs.h
 lib/getopt.h
 lib/inttypes.h
+lib/signal.h
 lib/stdbool.h
 lib/stdio.h
 lib/stdint.h

=== modified file 'ChangeLog'
--- ChangeLog	2011-07-06 16:42:05 +0000
+++ ChangeLog	2011-07-06 16:49:44 +0000
@@ -20,15 +20,18 @@
 	This contains just the automatically-generated stuff from gnulib;
 	a later patch will contain the more-interesting stuff.
 	* lib/dtotimespec.c, lib/errno.in.h, lib/gettime.c:
-	* lib/gettimeofday.c, lib/pselect.c, lib/stat-time.h, lib/strtoll.c:
+	* lib/gettimeofday.c, lib/pselect.c, lib/signal.in.h:
+	* lib/stat-time.h, lib/strtoll.c:
 	* 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/errno_h.m4, m4/gettime.m4, m4/gettimeofday.m4:
-	* m4/pselect.m4, m4/stat-time.m4, m4/strtoimax.m4, m4/strtoll.m4:
+	* m4/pselect.m4, m4/pthread_sigmask.m4, m4/signal_h.m4:
+	* m4/stat-time.m4, m4/strtoimax.m4, m4/strtoll.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/gl-comp.m4: Merge from gnulib.
+	* .bzrignore: Add lib/signal.h.
 
 2011-07-05  Jan Djärv  <jan.h.d <at> swipnet.se>
 

=== modified file 'lib/gnulib.mk'
--- lib/gnulib.mk	2011-07-01 06:13:09 +0000
+++ lib/gnulib.mk	2011-07-06 16:49:44 +0000
@@ -9,7 +9,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=. --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 lstat mktime pselect readlink socklen stat-time stdarg stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timespec-add timespec-sub utimens
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --avoid=select --avoid=sigprocmask --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 lstat mktime pselect readlink socklen stat-time stdarg stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timespec-add timespec-sub utimens
 
 
 MOSTLYCLEANFILES += core *.stackdump
@@ -367,6 +367,44 @@
 
 ## end   gnulib module readlink
 
+## begin gnulib module signal
+
+BUILT_SOURCES += signal.h
+
+# We need the following in order to create <signal.h> when the system
+# doesn't have a complete one.
+signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(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_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
+	      -e 's|@''GNULIB_PTHREAD_SIGMASK''@|$(GNULIB_PTHREAD_SIGMASK)|g' \
+	      -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \
+	      -e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \
+	      -e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \
+	      -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \
+	      -e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \
+	      -e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \
+	      -e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \
+	      -e 's|@''HAVE_STRUCT_SIGACTION_SA_SIGACTION''@|$(HAVE_STRUCT_SIGACTION_SA_SIGACTION)|g' \
+	      -e 's|@''HAVE_TYPE_VOLATILE_SIG_ATOMIC_T''@|$(HAVE_TYPE_VOLATILE_SIG_ATOMIC_T)|g' \
+	      -e 's|@''HAVE_SIGHANDLER_T''@|$(HAVE_SIGHANDLER_T)|g' \
+	      -e 's|@''REPLACE_PTHREAD_SIGMASK''@|$(REPLACE_PTHREAD_SIGMASK)|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)/signal.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += signal.h signal.h-t
+
+EXTRA_DIST += signal.in.h
+
+## end   gnulib module signal
+
 ## begin gnulib module stat
 
 if gl_GNULIB_ENABLED_stat

=== modified file 'lib/pselect.c'
--- lib/pselect.c	2011-07-01 06:13:09 +0000
+++ lib/pselect.c	2011-07-06 16:49:44 +0000
@@ -27,8 +27,6 @@
 #include <errno.h>
 #include <signal.h>
 
-#undef pselect
-
 /* Examine the size-NFDS file descriptor sets in RFDS, WFDS, and XFDS
    to see whether some of their descriptors are ready for reading,
    ready for writing, or have exceptions pending.  Wait for at most
@@ -37,10 +35,10 @@
    or an unaffected signal mask.  */
 
 int
-rpl_pselect (int nfds, fd_set *restrict rfds,
-             fd_set *restrict wfds, fd_set *restrict xfds,
-             struct timespec const *restrict timeout,
-             sigset_t const *restrict sigmask)
+pselect (int nfds, fd_set *restrict rfds,
+         fd_set *restrict wfds, fd_set *restrict xfds,
+         struct timespec const *restrict timeout,
+         sigset_t const *restrict sigmask)
 {
   int select_result;
   sigset_t origmask;
@@ -64,14 +62,14 @@
   /* Signal mask munging should be atomic, but this is the best we can
      do in this emulation.  */
   if (sigmask)
-    sigprocmask (SIG_SETMASK, sigmask, &origmask);
+    pthread_sigmask (SIG_SETMASK, sigmask, &origmask);
 
   select_result = select (nfds, rfds, wfds, xfds, tvp);
 
   if (sigmask)
     {
       int select_errno = errno;
-      sigprocmask (SIG_SETMASK, &origmask, NULL);
+      pthread_sigmask (SIG_SETMASK, &origmask, NULL);
       errno = select_errno;
     }
 

=== added file 'lib/signal.in.h'
--- lib/signal.in.h	1970-01-01 00:00:00 +0000
+++ lib/signal.in.h	2011-07-06 16:49:44 +0000
@@ -0,0 +1,392 @@
+/* A GNU-like <signal.h>.
+
+   Copyright (C) 2006-2011 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+#if defined __need_sig_atomic_t || defined __need_sigset_t
+/* Special invocation convention inside glibc header files.  */
+
+# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@
+
+#else
+/* Normal invocation convention.  */
+
+#ifndef _ <at> GUARD_PREFIX <at> _SIGNAL_H
+
+/* Define pid_t, uid_t.
+   Also, mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.
+   On Solaris 10, <signal.h> includes <sys/types.h>, which eventually includes
+   us; so include <sys/types.h> now, before the second inclusion guard.  */
+#include <sys/types.h>
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@
+
+#ifndef _ <at> GUARD_PREFIX <at> _SIGNAL_H
+#define _ <at> GUARD_PREFIX <at> _SIGNAL_H
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+/* On AIX, sig_atomic_t already includes volatile.  C99 requires that
+   'volatile sig_atomic_t' ignore the extra modifier, but C89 did not.
+   Hence, redefine this to a non-volatile type as needed.  */
+#if ! @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@
+# if !GNULIB_defined_sig_atomic_t
+typedef int rpl_sig_atomic_t;
+#  undef sig_atomic_t
+#  define sig_atomic_t rpl_sig_atomic_t
+#  define GNULIB_defined_sig_atomic_t 1
+# endif
+#endif
+
+/* A set or mask of signals.  */
+#if !@HAVE_SIGSET_T@
+# if !GNULIB_defined_sigset_t
+typedef unsigned int sigset_t;
+#  define GNULIB_defined_sigset_t 1
+# endif
+#endif
+
+/* Define sighandler_t, the type of signal handlers.  A GNU extension.  */
+#if !@HAVE_SIGHANDLER_T@
+# ifdef __cplusplus
+extern "C" {
+# endif
+# if !GNULIB_defined_sighandler_t
+typedef void (*sighandler_t) (int);
+#  define GNULIB_defined_sighandler_t 1
+# endif
+# ifdef __cplusplus
+}
+# endif
+#endif
+
+
+#if @GNULIB_SIGNAL_H_SIGPIPE@
+# ifndef SIGPIPE
+/* Define SIGPIPE to a value that does not overlap with other signals.  */
+#  define SIGPIPE 13
+#  define GNULIB_defined_SIGPIPE 1
+/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask',
+   'write', 'stdio'.  */
+# endif
+#endif
+
+
+/* Maximum signal number + 1.  */
+#ifndef NSIG
+# if defined __TANDEM
+#  define NSIG 32
+# endif
+#endif
+
+
+#if @GNULIB_PTHREAD_SIGMASK@
+# if @REPLACE_PTHREAD_SIGMASK@
+#  undef pthread_sigmask
+#  define pthread_sigmask sigprocmask
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef pthread_sigmask
+# if HAVE_RAW_DECL_PTHREAD_SIGMASK
+_GL_WARN_ON_USE (pthread_sigmask, "pthread_sigmask is not portable - "
+                 "use gnulib module pthread_sigmask for portability");
+# endif
+#endif
+
+
+#if @GNULIB_SIGPROCMASK@
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+
+/* Maximum signal number + 1.  */
+#  ifndef NSIG
+#   define NSIG 32
+#  endif
+
+/* This code supports only 32 signals.  */
+#  if !GNULIB_defined_verify_NSIG_constraint
+typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1];
+#   define GNULIB_defined_verify_NSIG_constraint 1
+#  endif
+
+# endif
+
+/* Test whether a given signal is contained in a signal set.  */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X.  */
+#  if defined __cplusplus && defined GNULIB_NAMESPACE
+#   undef sigismember
+#  endif
+# else
+_GL_FUNCDECL_SYS (sigismember, int, (const sigset_t *set, int sig)
+                                    _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigismember, int, (const sigset_t *set, int sig));
+_GL_CXXALIASWARN (sigismember);
+
+/* Initialize a signal set to the empty set.  */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X.  */
+#  if defined __cplusplus && defined GNULIB_NAMESPACE
+#   undef sigemptyset
+#  endif
+# else
+_GL_FUNCDECL_SYS (sigemptyset, int, (sigset_t *set) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigemptyset, int, (sigset_t *set));
+_GL_CXXALIASWARN (sigemptyset);
+
+/* Add a signal to a signal set.  */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X.  */
+#  if defined __cplusplus && defined GNULIB_NAMESPACE
+#   undef sigaddset
+#  endif
+# else
+_GL_FUNCDECL_SYS (sigaddset, int, (sigset_t *set, int sig)
+                                  _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigaddset, int, (sigset_t *set, int sig));
+_GL_CXXALIASWARN (sigaddset);
+
+/* Remove a signal from a signal set.  */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X.  */
+#  if defined __cplusplus && defined GNULIB_NAMESPACE
+#   undef sigdelset
+#  endif
+# else
+_GL_FUNCDECL_SYS (sigdelset, int, (sigset_t *set, int sig)
+                                  _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigdelset, int, (sigset_t *set, int sig));
+_GL_CXXALIASWARN (sigdelset);
+
+/* Fill a signal set with all possible signals.  */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X.  */
+#  if defined __cplusplus && defined GNULIB_NAMESPACE
+#   undef sigfillset
+#  endif
+# else
+_GL_FUNCDECL_SYS (sigfillset, int, (sigset_t *set) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigfillset, int, (sigset_t *set));
+_GL_CXXALIASWARN (sigfillset);
+
+/* Return the set of those blocked signals that are pending.  */
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+_GL_FUNCDECL_SYS (sigpending, int, (sigset_t *set) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigpending, int, (sigset_t *set));
+_GL_CXXALIASWARN (sigpending);
+
+/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET.
+   Then, if SET is not NULL, affect the current set of blocked signals by
+   combining it with *SET as indicated in OPERATION.
+   In this implementation, you are not allowed to change a signal handler
+   while the signal is blocked.  */
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+#  define SIG_BLOCK   0  /* blocked_set = blocked_set | *set; */
+#  define SIG_SETMASK 1  /* blocked_set = *set; */
+#  define SIG_UNBLOCK 2  /* blocked_set = blocked_set & ~*set; */
+_GL_FUNCDECL_SYS (sigprocmask, int,
+                  (int operation, const sigset_t *set, sigset_t *old_set));
+# endif
+_GL_CXXALIAS_SYS (sigprocmask, int,
+                  (int operation, const sigset_t *set, sigset_t *old_set));
+_GL_CXXALIASWARN (sigprocmask);
+
+/* Install the handler FUNC for signal SIG, and return the previous
+   handler.  */
+# ifdef __cplusplus
+extern "C" {
+# endif
+# if !GNULIB_defined_function_taking_int_returning_void_t
+typedef void (*_gl_function_taking_int_returning_void_t) (int);
+#  define GNULIB_defined_function_taking_int_returning_void_t 1
+# endif
+# ifdef __cplusplus
+}
+# endif
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   define signal rpl_signal
+#  endif
+_GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t,
+                  (int sig, _gl_function_taking_int_returning_void_t func));
+_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t,
+                  (int sig, _gl_function_taking_int_returning_void_t func));
+# else
+_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t,
+                  (int sig, _gl_function_taking_int_returning_void_t func));
+# endif
+_GL_CXXALIASWARN (signal);
+
+/* Raise signal SIG.  */
+# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef raise
+#   define raise rpl_raise
+#  endif
+_GL_FUNCDECL_RPL (raise, int, (int sig));
+_GL_CXXALIAS_RPL (raise, int, (int sig));
+# else
+_GL_CXXALIAS_SYS (raise, int, (int sig));
+# endif
+_GL_CXXALIASWARN (raise);
+
+#elif defined GNULIB_POSIXCHECK
+# undef sigaddset
+# if HAVE_RAW_DECL_SIGADDSET
+_GL_WARN_ON_USE (sigaddset, "sigaddset is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigdelset
+# if HAVE_RAW_DECL_SIGDELSET
+_GL_WARN_ON_USE (sigdelset, "sigdelset is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigemptyset
+# if HAVE_RAW_DECL_SIGEMPTYSET
+_GL_WARN_ON_USE (sigemptyset, "sigemptyset is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigfillset
+# if HAVE_RAW_DECL_SIGFILLSET
+_GL_WARN_ON_USE (sigfillset, "sigfillset is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigismember
+# if HAVE_RAW_DECL_SIGISMEMBER
+_GL_WARN_ON_USE (sigismember, "sigismember is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigpending
+# if HAVE_RAW_DECL_SIGPENDING
+_GL_WARN_ON_USE (sigpending, "sigpending is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigprocmask
+# if HAVE_RAW_DECL_SIGPROCMASK
+_GL_WARN_ON_USE (sigprocmask, "sigprocmask is unportable - "
+                 "use the gnulib module sigprocmask for portability");
+# endif
+#endif /* @GNULIB_SIGPROCMASK@ */
+
+
+#if @GNULIB_SIGACTION@
+# if !@HAVE_SIGACTION@
+
+#  if !@HAVE_SIGINFO_T@
+
+#   if !GNULIB_defined_siginfo_types
+
+/* Present to allow compilation, but unsupported by gnulib.  */
+union sigval
+{
+  int sival_int;
+  void *sival_ptr;
+};
+
+/* Present to allow compilation, but unsupported by gnulib.  */
+struct siginfo_t
+{
+  int si_signo;
+  int si_code;
+  int si_errno;
+  pid_t si_pid;
+  uid_t si_uid;
+  void *si_addr;
+  int si_status;
+  long si_band;
+  union sigval si_value;
+};
+typedef struct siginfo_t siginfo_t;
+
+#    define GNULIB_defined_siginfo_types 1
+#   endif
+
+#  endif /* !@HAVE_SIGINFO_T@ */
+
+/* We assume that platforms which lack the sigaction() function also lack
+   the 'struct sigaction' type, and vice versa.  */
+
+#  if !GNULIB_defined_struct_sigaction
+
+struct sigaction
+{
+  union
+  {
+    void (*_sa_handler) (int);
+    /* Present to allow compilation, but unsupported by gnulib.  POSIX
+       says that implementations may, but not must, make sa_sigaction
+       overlap with sa_handler, but we know of no implementation where
+       they do not overlap.  */
+    void (*_sa_sigaction) (int, siginfo_t *, void *);
+  } _sa_func;
+  sigset_t sa_mask;
+  /* Not all POSIX flags are supported.  */
+  int sa_flags;
+};
+#   define sa_handler _sa_func._sa_handler
+#   define sa_sigaction _sa_func._sa_sigaction
+/* Unsupported flags are not present.  */
+#   define SA_RESETHAND 1
+#   define SA_NODEFER 2
+#   define SA_RESTART 4
+
+#   define GNULIB_defined_struct_sigaction 1
+#  endif
+
+_GL_FUNCDECL_SYS (sigaction, int, (int, const struct sigaction *restrict,
+                                   struct sigaction *restrict));
+
+# elif !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@
+
+#  define sa_sigaction sa_handler
+
+# endif /* !@HAVE_SIGACTION@, !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ */
+
+_GL_CXXALIAS_SYS (sigaction, int, (int, const struct sigaction *restrict,
+                                   struct sigaction *restrict));
+_GL_CXXALIASWARN (sigaction);
+
+#elif defined GNULIB_POSIXCHECK
+# undef sigaction
+# if HAVE_RAW_DECL_SIGACTION
+_GL_WARN_ON_USE (sigaction, "sigaction is unportable - "
+                 "use the gnulib module sigaction for portability");
+# endif
+#endif
+
+/* Some systems don't have SA_NODEFER.  */
+#ifndef SA_NODEFER
+# define SA_NODEFER 0
+#endif
+
+
+#endif /* _ <at> GUARD_PREFIX <at> _SIGNAL_H */
+#endif /* _ <at> GUARD_PREFIX <at> _SIGNAL_H */
+#endif

=== modified file 'lib/sys_select.in.h'
--- lib/sys_select.in.h	2011-07-01 06:13:09 +0000
+++ lib/sys_select.in.h	2011-07-06 16:49:44 +0000
@@ -36,12 +36,19 @@
 
 #ifndef _ <at> GUARD_PREFIX <at> _SYS_SELECT_H
 
+/* On many platforms, <sys/select.h> assumes prior inclusion of
+   <sys/types.h>.  Also, mingw defines sigset_t there, instead of
+   in <signal.h> where it belongs.  */
+#include <sys/types.h>
+
+/* Get definition of 'sigset_t'.
+   But avoid namespace pollution on glibc systems.  */
+#if !(defined __GLIBC__ && !defined __UCLIBC__)
+# include <signal.h>
+#endif
+
 #if @HAVE_SYS_SELECT_H@
 
-/* On many platforms, <sys/select.h> assumes prior inclusion of
-   <sys/types.h>.  */
-# include <sys/types.h>
-
 /* On OSF/1 4.0, <sys/select.h> provides only a forward declaration
    of 'struct timeval', and no definition of this type.
    Also, MacOS X, AIX, HP-UX, IRIX, Solaris, Interix declare select()
@@ -77,20 +84,12 @@
 # if defined __hpux
 #  include <string.h>
 # endif
-/* On native Windows platforms:
-   Get the 'fd_set' type.  Also, gnulib's <sys/socket.h> redefines select
-   so as to hide the declaration from <winsock2.h>.  */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-#  include <sys/socket.h>
+/* On native Windows platforms, get the 'fd_set' type and related macros.  */
+# if @HAVE_WINSOCK2_H@
+#  include <winsock2.h>
 # endif
 #endif
 
-/* Get definition of 'sigset_t'.
-   But avoid namespace pollution on glibc systems.  */
-#if !(defined __GLIBC__ && !defined __UCLIBC__)
-# include <signal.h>
-#endif
-
 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
 
 /* The definition of _GL_WARN_ON_USE is copied here.  */

=== modified file 'm4/gl-comp.m4'
--- m4/gl-comp.m4	2011-07-01 06:13:09 +0000
+++ m4/gl-comp.m4	2011-07-06 16:49:44 +0000
@@ -58,7 +58,9 @@
   # Code from module mktime:
   # Code from module multiarch:
   # Code from module pselect:
+  # Code from module pthread_sigmask:
   # Code from module readlink:
+  # Code from module signal:
   # Code from module socklen:
   # Code from module ssize_t:
   # Code from module stat:
@@ -165,7 +167,7 @@
 gl_TIME_MODULE_INDICATOR([mktime])
 gl_MULTIARCH
 gl_FUNC_PSELECT
-if test $REPLACE_PSELECT = 1; then
+if test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1; then
   AC_LIBOBJ([pselect])
 fi
 gl_SYS_SELECT_MODULE_INDICATOR([pselect])
@@ -175,6 +177,7 @@
   gl_PREREQ_READLINK
 fi
 gl_UNISTD_MODULE_INDICATOR([readlink])
+gl_SIGNAL_H
 gl_TYPE_SOCKLEN_T
 gt_TYPE_SSIZE_T
 gl_STAT_TIME
@@ -222,6 +225,7 @@
 gl_UTIMENS
   gl_gnulib_enabled_dosname=false
   gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
+  gl_gnulib_enabled_pthread_sigmask=false
   gl_gnulib_enabled_stat=false
   gl_gnulib_enabled_strtoll=false
   gl_gnulib_enabled_strtoull=false
@@ -240,6 +244,17 @@
       gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=true
     fi
   }
+  func_gl_gnulib_m4code_pthread_sigmask ()
+  {
+    if ! $gl_gnulib_enabled_pthread_sigmask; then
+gl_PTHREAD_SIGMASK
+gl_SYS_SELECT_MODULE_INDICATOR([pthread_sigmask])
+      gl_gnulib_enabled_pthread_sigmask=true
+      if $condition; then
+        func_gl_gnulib_m4code_sigprocmask
+      fi
+    fi
+  }
   func_gl_gnulib_m4code_stat ()
   {
     if ! $gl_gnulib_enabled_stat; then
@@ -297,6 +312,12 @@
   if test $REPLACE_LSTAT = 1; then
     func_gl_gnulib_m4code_stat
   fi
+  if test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1; then
+    func_gl_gnulib_m4code_pthread_sigmask
+  fi
+  if test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1; then
+    func_gl_gnulib_m4code_select
+  fi
   if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
     func_gl_gnulib_m4code_stat
   fi
@@ -315,6 +336,7 @@
   m4_pattern_allow([^gl_GNULIB_ENABLED_])
   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_pthread_sigmask], [$gl_gnulib_enabled_pthread_sigmask])
   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])
@@ -501,6 +523,7 @@
   lib/sha256.h
   lib/sha512.c
   lib/sha512.h
+  lib/signal.in.h
   lib/stat-time.h
   lib/stat.c
   lib/stdarg.in.h
@@ -552,10 +575,12 @@
   m4/mktime.m4
   m4/multiarch.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/socklen.m4
   m4/ssize_t.m4
   m4/st_dm_mode.m4

=== modified file 'm4/pselect.m4'
--- m4/pselect.m4	2011-07-01 06:13:09 +0000
+++ m4/pselect.m4	2011-07-06 16:49:44 +0000
@@ -14,15 +14,15 @@
     AC_CACHE_CHECK([whether signature of pselect conforms to POSIX],
       gl_cv_sig_pselect,
       [AC_LINK_IFELSE(
-	 [AC_LANG_PROGRAM(
-	      [[#include <sys/select.h>
-		]],
-	      [[int (*p) (int, fd_set *, fd_set *, fd_set *restrict,
-			  struct timespec const *restrict,
-			  sigset_t const *restrict) = pselect;
-		return !p;]])],
-	 [gl_cv_sig_pselect=yes],
-	 [gl_cv_sig_pselect=no])])
+         [AC_LANG_PROGRAM(
+              [[#include <sys/select.h>
+                ]],
+              [[int (*p) (int, fd_set *, fd_set *, fd_set *restrict,
+                          struct timespec const *restrict,
+                          sigset_t const *restrict) = pselect;
+                return !p;]])],
+         [gl_cv_sig_pselect=yes],
+         [gl_cv_sig_pselect=no])])
   fi
 
   if test $ac_cv_func_pselect = no || test $gl_cv_sig_pselect = no; then

=== added file 'm4/pthread_sigmask.m4'
--- m4/pthread_sigmask.m4	1970-01-01 00:00:00 +0000
+++ m4/pthread_sigmask.m4	2011-07-06 16:49:44 +0000
@@ -0,0 +1,24 @@
+# pthread_sigmask.m4 serial 1
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_PTHREAD_SIGMASK],
+[
+  m4_ifdef([gl_THREADLIB], [
+    AC_REQUIRE([gl_THREADLIB])
+    if test "$gl_threads_api" = posix; then
+      gl_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBMULTITHREAD"
+      AC_CHECK_FUNCS([pthread_sigmask])
+      LIBS="$gl_save_LIBS"
+    fi
+  ], [
+    AC_CHECK_FUNCS_ONCE([pthread_sigmask])
+  ])
+
+  if test $ac_cv_func_pthread_sigmask = no; then
+    REPLACE_PTHREAD_SIGMASK=0
+  fi
+])

=== added file 'm4/signal_h.m4'
--- m4/signal_h.m4	1970-01-01 00:00:00 +0000
+++ m4/signal_h.m4	2011-07-06 16:49:44 +0000
@@ -0,0 +1,76 @@
+# signal_h.m4 serial 14
+dnl Copyright (C) 2007-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_SIGNAL_H],
+[
+  AC_REQUIRE([gl_SIGNAL_H_DEFAULTS])
+  AC_REQUIRE([gl_CHECK_TYPE_SIGSET_T])
+  gl_NEXT_HEADERS([signal.h])
+
+# AIX declares sig_atomic_t to already include volatile, and C89 compilers
+# then choke on 'volatile sig_atomic_t'.  C99 requires that it compile.
+  AC_CHECK_TYPE([volatile sig_atomic_t], [],
+    [HAVE_TYPE_VOLATILE_SIG_ATOMIC_T=0], [[
+#include <signal.h>
+    ]])
+
+  AC_REQUIRE([AC_TYPE_UID_T])
+
+  dnl Persuade glibc <signal.h> to define sighandler_t.
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+  AC_CHECK_TYPE([sighandler_t], [], [HAVE_SIGHANDLER_T=0], [[
+#include <signal.h>
+    ]])
+
+  dnl Check for declarations of anything we want to poison if the
+  dnl corresponding gnulib module is not in use.
+  gl_WARN_ON_USE_PREPARE([[#include <signal.h>
+    ]], [pthread_sigmask sigaction
+    sigaddset sigdelset sigemptyset sigfillset sigismember
+    sigpending sigprocmask])
+])
+
+AC_DEFUN([gl_CHECK_TYPE_SIGSET_T],
+[
+  AC_CHECK_TYPES([sigset_t],
+    [gl_cv_type_sigset_t=yes], [gl_cv_type_sigset_t=no],
+    [[
+      #include <signal.h>
+      /* Mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.  */
+      #include <sys/types.h>
+    ]])
+  if test $gl_cv_type_sigset_t != yes; then
+    HAVE_SIGSET_T=0
+  fi
+])
+
+AC_DEFUN([gl_SIGNAL_MODULE_INDICATOR],
+[
+  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+  AC_REQUIRE([gl_SIGNAL_H_DEFAULTS])
+  gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+  dnl Define it also as a C macro, for the benefit of the unit tests.
+  gl_MODULE_INDICATOR_FOR_TESTS([$1])
+])
+
+AC_DEFUN([gl_SIGNAL_H_DEFAULTS],
+[
+  GNULIB_PTHREAD_SIGMASK=0;    AC_SUBST([GNULIB_PTHREAD_SIGMASK])
+  GNULIB_SIGNAL_H_SIGPIPE=0;   AC_SUBST([GNULIB_SIGNAL_H_SIGPIPE])
+  GNULIB_SIGPROCMASK=0;        AC_SUBST([GNULIB_SIGPROCMASK])
+  GNULIB_SIGACTION=0;          AC_SUBST([GNULIB_SIGACTION])
+  dnl Assume proper GNU behavior unless another module says otherwise.
+  HAVE_POSIX_SIGNALBLOCKING=1; AC_SUBST([HAVE_POSIX_SIGNALBLOCKING])
+  HAVE_SIGSET_T=1;             AC_SUBST([HAVE_SIGSET_T])
+  HAVE_SIGINFO_T=1;            AC_SUBST([HAVE_SIGINFO_T])
+  HAVE_SIGACTION=1;            AC_SUBST([HAVE_SIGACTION])
+  HAVE_STRUCT_SIGACTION_SA_SIGACTION=1;
+                               AC_SUBST([HAVE_STRUCT_SIGACTION_SA_SIGACTION])
+  HAVE_TYPE_VOLATILE_SIG_ATOMIC_T=1;
+                               AC_SUBST([HAVE_TYPE_VOLATILE_SIG_ATOMIC_T])
+  HAVE_SIGHANDLER_T=1;         AC_SUBST([HAVE_SIGHANDLER_T])
+  REPLACE_PTHREAD_SIGMASK=0;   AC_SUBST([REPLACE_PTHREAD_SIGMASK])
+])

=== modified file 'm4/sys_select_h.m4'
--- m4/sys_select_h.m4	2011-07-01 06:13:09 +0000
+++ m4/sys_select_h.m4	2011-07-06 16:49:44 +0000
@@ -1,4 +1,4 @@
-# sys_select_h.m4 serial 18
+# sys_select_h.m4 serial 19
 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -64,7 +64,7 @@
 # include <sys/time.h>
 #endif
 #include <sys/select.h>
-    ]], [select])
+    ]], [pselect select])
 ])
 
 AC_DEFUN([gl_SYS_SELECT_MODULE_INDICATOR],






Added tag(s) patch. Request was from Paul Eggert <eggert <at> cs.ucla.edu> to control <at> debbugs.gnu.org. (Sat, 31 Dec 2011 08:46:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Fri, 04 May 2012 20:56:02 GMT) Full text and rfc822 format available.

Message #16 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: 9000 <at> debbugs.gnu.org
Subject: 2012-05-04 version of patch
Date: Fri, 04 May 2012 13:52:48 -0700
[Message part 1 (text/plain, inline)]
Attached is an updated version of the patch, relative
to the current trunk version (bzr 108124).  It's in
two parts.  The first part is to Emacs proper: this
actually shrinks the Emacs source code a bit,
by deleting 1047 lines and adding 934 lines, for
a savings of 113 lines.  The second part is the
changes automatically brought in from gnulib, which
either bring in new time-related modules or update
old modules, partly to update copyright notices.
The second part is long and boring and I've taken
the liberty of compressing it.
[emacs-ns-diff.txt (text/plain, attachment)]
[emacs-ns-gnulib-diff.txt.gz (application/x-gzip, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sun, 27 May 2012 03:11:02 GMT) Full text and rfc822 format available.

Message #19 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: 9000 <at> debbugs.gnu.org
Subject: Re: 2012-05-04 version of patch
Date: Sat, 26 May 2012 20:08:15 -0700
[Message part 1 (text/plain, inline)]
Attached is a revised update, which contains the
entire patch.  Since recent gnulib changes have
been merged, the new patch is smaller.
[emacs-ns-diff.txt.gz (application/x-gzip, attachment)]

Reply sent to Paul Eggert <eggert <at> cs.ucla.edu>:
You have taken responsibility. (Fri, 22 Jun 2012 21:26:01 GMT) Full text and rfc822 format available.

Notification sent to Paul Eggert <eggert <at> cs.ucla.edu>:
bug acknowledged by developer. (Fri, 22 Jun 2012 21:26:02 GMT) Full text and rfc822 format available.

Message #24 received at 9000-done <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: 9000-done <at> debbugs.gnu.org
Cc: Eli Zaretskii <eliz <at> gnu.org>
Subject: patch for higher-resolution time stamps
Date: Fri, 22 Jun 2012 14:21:50 -0700
No further comment and the patch seems ripe
so I installed it into the trunk as bzr 108687
and am marking this bug as done.  I'll CC: this
to Eli as it affects the Microsoft ports.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 08:45:02 GMT) Full text and rfc822 format available.

Message #27 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 11:39:40 +0300
> Date: Fri, 22 Jun 2012 14:21:50 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: Eli Zaretskii <eliz <at> gnu.org>
> 
> No further comment and the patch seems ripe
> so I installed it into the trunk as bzr 108687
> and am marking this bug as done.  I'll CC: this
> to Eli as it affects the Microsoft ports.

This badly broke the MS-Windows build.  I'm working on fixing it.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 10:53:02 GMT) Full text and rfc822 format available.

Message #30 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: eggert <at> cs.ucla.edu
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 13:48:41 +0300
> Date: Sat, 23 Jun 2012 11:39:40 +0300
> From: Eli Zaretskii <eliz <at> gnu.org>
> Cc: 9000 <at> debbugs.gnu.org
> 
> > Date: Fri, 22 Jun 2012 14:21:50 -0700
> > From: Paul Eggert <eggert <at> cs.ucla.edu>
> > CC: Eli Zaretskii <eliz <at> gnu.org>
> > 
> > No further comment and the patch seems ripe
> > so I installed it into the trunk as bzr 108687
> > and am marking this bug as done.  I'll CC: this
> > to Eli as it affects the Microsoft ports.
> 
> This badly broke the MS-Windows build.  I'm working on fixing it.

I think I fixed this in revision 108698, MS-Windows users please see
if there are any leftovers.  In particular, any feature that uses
system time or file time or 'select' (i.e. subprocesses) is suspect.
I only did some minimal testing.

Paul, please note that I needed changes in 3 gnulib headers:
utimens.h, timespec.h, and stat-time.h.  The change is to include
sys/time.h, because that's where the Windows build defines
'struct timespec' (time.h cannot be used for that).  I hope you can
make these changes in upstream gnulib.

I'm OK with any other solution to this conundrum, which will be
compatible with the following conditions:

 . do not assume that 'struct timespec' is defined on time.h, or on
   any other MS-Windows system header
 . do not use gnulib's time.h (as that requires Sed to edit time.in.h)

It is OK to add headers to Emacs's nt/inc/ directory in order to solve
this, provided that they do not shadow system headers (since MSVC does
not have include_next or its equivalent).

Finally, I see compiler warnings due to the changes in revno 108687:

  dispnew.c: In function `Fsleep_for':
  dispnew.c:5960: warning: comparison is always true due to limited range of data type
  dispnew.c: In function `sit_for':
  dispnew.c:6008: warning: comparison is always true due to limited range of data type

  keyboard.c: In function `kbd_buffer_get_event':
  keyboard.c:3861: warning: comparison is always true due to limited range of data type

  process.c: In function `Faccept_process_output':
  process.c:3999: warning: comparison is always true due to limited range of data type

They all come from snippets such as this one:

    min (EMACS_SECS (t), INTMAX_MAX)

I think any host with a signed 32-bit time_t will see this warning.
Can this annoyance be fixed, please?





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 18:02:01 GMT) Full text and rfc822 format available.

Message #33 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 10:57:31 -0700
On 06/23/2012 03:48 AM, Eli Zaretskii wrote:
>   dispnew.c:5960: warning: comparison is always true due to limited range of data type
> ...
> I think any host with a signed 32-bit time_t will see this warning.

I don't observe the problem on either Fedora 15 or Ubuntu 12.04
compiled for x86 (these used signed 32-bit time_t).  I tried both
gcc 4.6.3 and gcc 4.7.1 (which is the latest stable version).

If memory serves, warnings like that occur only with older GCCs and
are harmless, and the GCC folks fixed the bogus warnings after the
gnulib folks complained about them.  Maybe time to upgrade your GCC?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 19:00:02 GMT) Full text and rfc822 format available.

Message #36 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 11:55:37 -0700
On 06/23/2012 03:48 AM, Eli Zaretskii wrote:
>  . do not assume that 'struct timespec' is defined on time.h, or on
>    any other MS-Windows system header
>  . do not use gnulib's time.h (as that requires Sed to edit time.in.h)

OK, thanks, here's a proposed patch to do that.
I'd rather leave gnulib alone, since struct timeval has
nothing to do with sys/time.h in POSIX.

=== modified file 'ChangeLog'
--- ChangeLog	2012-06-23 17:25:56 +0000
+++ ChangeLog	2012-06-23 18:51:45 +0000
@@ -1,5 +1,10 @@
 2012-06-23  Paul Eggert  <eggert <at> cs.ucla.edu>
 
+	Improve port of struct timespec to MS-Windows.
+	* lib/stat-time.h, lib/timespec.h, lib/utimens.h:
+	Do not include sys/time.h.  This reverts the most recent change,
+	so that these files stay in step with gnulib.
+
 	Merge from gnulib.
 	* m4/getopt.m4: Copy new version from gnulib, incorporating:
 	getopt-gnu: Handle suboptimal getopt_long's abbreviation handling.

=== modified file 'lib/stat-time.h'
--- lib/stat-time.h	2012-06-23 10:22:59 +0000
+++ lib/stat-time.h	2012-06-23 18:51:45 +0000
@@ -22,7 +22,6 @@
 
 #include <sys/stat.h>
 #include <time.h>
-#include <sys/time.h>
 
 /* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
    struct timespec, if available.  If not, then STAT_TIMESPEC_NS (ST,

=== modified file 'lib/timespec.h'
--- lib/timespec.h	2012-06-23 10:22:59 +0000
+++ lib/timespec.h	2012-06-23 18:51:45 +0000
@@ -20,7 +20,6 @@
 # define TIMESPEC_H
 
 # include <time.h>
-# include <sys/time.h>
 
 /* Return negative, zero, positive if A < B, A == B, A > B, respectively.
 

=== modified file 'lib/utimens.h'
--- lib/utimens.h	2012-06-23 10:22:59 +0000
+++ lib/utimens.h	2012-06-23 18:51:45 +0000
@@ -1,5 +1,4 @@
 #include <time.h>
-#include <sys/time.h>
 int fdutimens (int, char const *, struct timespec const [2]);
 int utimens (char const *, struct timespec const [2]);
 int lutimens (char const *, struct timespec const [2]);

=== modified file 'nt/ChangeLog'
--- nt/ChangeLog	2012-06-23 10:22:59 +0000
+++ nt/ChangeLog	2012-06-23 18:51:45 +0000
@@ -1,3 +1,8 @@
+2012-06-23  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Improve port of struct timespec to MS-Windows.
+	* inc/sys/time.h (struct timespec): Remove, undoing previous change.
+
 2012-06-23  Eli Zaretskii  <eliz <at> gnu.org>
 
 	Fix the MS-Windows build broken by revno 108687.

=== modified file 'nt/inc/sys/time.h'
--- nt/inc/sys/time.h	2012-06-23 10:22:59 +0000
+++ nt/inc/sys/time.h	2012-06-23 18:51:45 +0000
@@ -17,15 +17,8 @@
   int		tz_dsttime;	/* type of dst correction */
 };
 
-struct timespec
-{
-  time_t	tv_sec;		/* seconds */
-  long int	tv_nsec;	/* nanoseconds */
-};
-
 void gettimeofday (struct timeval *, struct timezone *);
 
 #endif /* SYS_TIME_H_INCLUDED */
 
 /* end of sys/time.h */
-

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-06-23 16:56:47 +0000
+++ src/ChangeLog	2012-06-23 18:51:45 +0000
@@ -1,3 +1,8 @@
+2012-06-23  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Improve port of struct timespec to MS-Windows.
+	* s/ms-w32.h (struct timespec) [_MSC_VER]: New decl.
+
 2012-06-23  Juanma Barranquero  <lekktu <at> gmail.com>
 
 	* w32.c (ltime): Add return type and declare static.

=== modified file 'src/s/ms-w32.h'
--- src/s/ms-w32.h	2012-06-23 10:22:59 +0000
+++ src/s/ms-w32.h	2012-06-23 18:54:35 +0000
@@ -296,6 +296,15 @@
 #define utime	  _utime
 #endif
 
+#ifdef _MSC_VER
+/* MSVC does not define struct timespec in <time.h>.  */
+struct timespec
+{
+  time_t	tv_sec;		/* seconds */
+  long int	tv_nsec;	/* nanoseconds */
+};
+#endif
+
 /* This is hacky, but is necessary to avoid warnings about macro
    redefinitions using the SDK compilers.  */
 #ifndef __STDC__




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 19:13:02 GMT) Full text and rfc822 format available.

Message #39 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 22:08:27 +0300
> Date: Sat, 23 Jun 2012 11:55:37 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 9000 <at> debbugs.gnu.org
> 
> === modified file 'src/s/ms-w32.h'
> --- src/s/ms-w32.h	2012-06-23 10:22:59 +0000
> +++ src/s/ms-w32.h	2012-06-23 18:54:35 +0000
> @@ -296,6 +296,15 @@
>  #define utime	  _utime
>  #endif
>  
> +#ifdef _MSC_VER
> +/* MSVC does not define struct timespec in <time.h>.  */
> +struct timespec
> +{
> +  time_t	tv_sec;		/* seconds */
> +  long int	tv_nsec;	/* nanoseconds */
> +};
> +#endif

I don't get it: are you trying to fix only the MSVC build?  If not,
where are the bits for MinGW?  What did I miss?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 19:14:02 GMT) Full text and rfc822 format available.

Message #42 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 22:09:26 +0300
> Date: Sat, 23 Jun 2012 10:57:31 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 9000 <at> debbugs.gnu.org
> 
> On 06/23/2012 03:48 AM, Eli Zaretskii wrote:
> >   dispnew.c:5960: warning: comparison is always true due to limited range of data type
> > ...
> > I think any host with a signed 32-bit time_t will see this warning.
> 
> I don't observe the problem on either Fedora 15 or Ubuntu 12.04
> compiled for x86 (these used signed 32-bit time_t).  I tried both
> gcc 4.6.3 and gcc 4.7.1 (which is the latest stable version).
> 
> If memory serves, warnings like that occur only with older GCCs and
> are harmless, and the GCC folks fixed the bogus warnings after the
> gnulib folks complained about them.  Maybe time to upgrade your GCC?

No, I don't want to upgrade my GCC because of this.  Is it possible to
fix the cause of the warning instead?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 19:47:01 GMT) Full text and rfc822 format available.

Message #45 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: eggert <at> cs.ucla.edu
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 22:42:26 +0300
> Date: Sat, 23 Jun 2012 22:09:26 +0300
> From: Eli Zaretskii <eliz <at> gnu.org>
> Cc: 9000 <at> debbugs.gnu.org
> 
> > Date: Sat, 23 Jun 2012 10:57:31 -0700
> > From: Paul Eggert <eggert <at> cs.ucla.edu>
> > CC: 9000 <at> debbugs.gnu.org
> > 
> > On 06/23/2012 03:48 AM, Eli Zaretskii wrote:
> > >   dispnew.c:5960: warning: comparison is always true due to limited range of data type
> > > ...
> > > I think any host with a signed 32-bit time_t will see this warning.
> > 
> > I don't observe the problem on either Fedora 15 or Ubuntu 12.04
> > compiled for x86 (these used signed 32-bit time_t).  I tried both
> > gcc 4.6.3 and gcc 4.7.1 (which is the latest stable version).
> > 
> > If memory serves, warnings like that occur only with older GCCs and
> > are harmless, and the GCC folks fixed the bogus warnings after the
> > gnulib folks complained about them.  Maybe time to upgrade your GCC?
> 
> No, I don't want to upgrade my GCC because of this.  Is it possible to
> fix the cause of the warning instead?

Never mind, I fixed that myself.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 22:39:02 GMT) Full text and rfc822 format available.

Message #48 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 15:34:27 -0700
On 06/23/2012 12:08 PM, Eli Zaretskii wrote:
> I don't get it: are you trying to fix only the MSVC build?  If not,
> where are the bits for MinGW?

Sorry, no, I assumed the problem only occurred with MSVC.
If it occurs on all Windows platforms, simply remove
the "#ifdef _MSC_VER" in question.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sat, 23 Jun 2012 22:50:02 GMT) Full text and rfc822 format available.

Message #51 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 15:45:26 -0700
On 06/23/2012 12:42 PM, Eli Zaretskii wrote:
> Never mind, I fixed that myself.

Unfortunately the patch that you installed can break
Emacs on hosts where time_t is unsigned, because
it assigns time_t values to intmax_t variables,
and this does not always work correctly when
INTMAX_MAX < TIME_T_MAX.

Which version of GCC are you running?
What is INTMAX_MAX defined to, on your platform?

Does it work to pacify your old GCC if you
replace this:

      intmax_t secs = EMACS_SECS (t);

      wait_reading_process_output (min (secs, INTMAX_MAX),
                                   EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);

with this?

      intmax_t max = INTMAX_MAX;

      wait_reading_process_output (min (secs, max),
                                   EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);

Or how about this?

static intmax_t intmax_max = INTMAX_MAX;
...    
      wait_reading_process_output (min (secs, intmax_max),
                                   EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);

We could make this latter rewrite conditional only for older
GCC versions.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sun, 24 Jun 2012 03:02:02 GMT) Full text and rfc822 format available.

Message #54 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sun, 24 Jun 2012 05:57:57 +0300
> Date: Sat, 23 Jun 2012 15:45:26 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 9000 <at> debbugs.gnu.org
> 
> On 06/23/2012 12:42 PM, Eli Zaretskii wrote:
> > Never mind, I fixed that myself.
> 
> Unfortunately the patch that you installed can break
> Emacs on hosts where time_t is unsigned, because
> it assigns time_t values to intmax_t variables,
> and this does not always work correctly when
> INTMAX_MAX < TIME_T_MAX.

We could use (UINTMAX_MAX / 2) instead, would that work?

> Which version of GCC are you running?

3.4.2

> What is INTMAX_MAX defined to, on your platform?

It is defined to INT64_MAX (i.e., 9223372036854775807LL).  The problem
is that EMACS_SECS returns a time_t, a 32-bit value, whereas
INTMAX_MAX is a 64-bit value.

> Does it work to pacify your old GCC if you
> replace this:
> 
>       intmax_t secs = EMACS_SECS (t);
> 
>       wait_reading_process_output (min (secs, INTMAX_MAX),
>                                    EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);
> 
> with this?
> 
>       intmax_t max = INTMAX_MAX;
> 
>       wait_reading_process_output (min (secs, max),
>                                    EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);

You don't show what is 'secs' in this snippet.  The key to avoiding
the warning is to have both arguments of 'min' be 64-bit values.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sun, 24 Jun 2012 04:36:01 GMT) Full text and rfc822 format available.

Message #57 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sat, 23 Jun 2012 21:31:38 -0700
On 06/23/2012 07:57 PM, Eli Zaretskii wrote:
> We could use (UINTMAX_MAX / 2) instead, would that work?

I don't think so, as the buggy compiler would still complain.

> The key to avoiding the warning is to have both arguments of 'min'
> be 64-bit values.

In my experience the width of the constant is irrelevant; what matters
is its value.  If an obsolete buggy GCC sees "E < C" where E is an
integer expression and C is a positive constant that is out of E's
type's range, it sometimes proudly reports that it is optimizing the
comparison away.  These warnings are typically bogus, and this was
considered a bug in GCC that was eventually fixed; the warnings
certainly are bogus for Emacs.

Normally we should not worry about silencing bogus warnings from
obsolete compilers, particularly when attempts to silence them are
liable to make the code less reliable or readable.  I suppose we can
make an exception here but I hope this doesn't establish a precedent.

I rummaged around our servers and found an old GCC that issues the
diagnostic, and installed as trunk bzr 108714 a further patch to silence
those particular warnings without introducing a signedness bug.
Here's our combined patch:


=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-06-23 19:28:01 +0000
+++ src/ChangeLog	2012-06-24 04:11:19 +0000
@@ -1,3 +1,22 @@
+2012-06-24  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Fix bug when time_t is unsigned and as wide as intmax_t (Bug#9000).
+	* lisp.h (WAIT_READING_MAX): New macro.
+	* dispnew.c (Fsleep_for, sit_for):
+	* keyboard.c (kbd_buffer_get_event):
+	* process.c (Faccept_process_output):
+	Use it to avoid bogus compiler warnings with obsolescent GCC versions.
+	This improves on the previous patch, which introduced a bug
+	when time_t is unsigned and as wide as intmax_t.
+	See <http://bugs.gnu.org/9000#51>.
+
+2012-06-23  Eli Zaretskii  <eliz <at> gnu.org>
+
+	* dispnew.c (sit_for, Fsleep_for):
+	* keyboard.c (kbd_buffer_get_event):
+	* process.c (Faccept_process_output): Avoid compiler warnings when
+	comparing a 32-bit time_t with a 64-bit INTMAX_MAX.
+
 2012-06-23  Juanma Barranquero  <lekktu <at> gmail.com>
 
 	* makefile.w32-in: Update dependencies.

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2012-06-22 21:17:42 +0000
+++ src/dispnew.c	2012-06-24 04:11:19 +0000
@@ -5957,7 +5957,7 @@
   if (0 < duration)
     {
       EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (duration);
-      wait_reading_process_output (min (EMACS_SECS (t), INTMAX_MAX),
+      wait_reading_process_output (min (EMACS_SECS (t), WAIT_READING_MAX),
 				   EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);
     }
 
@@ -6005,7 +6005,7 @@
       else
 	{
 	  EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (seconds);
-	  sec = min (EMACS_SECS (t), INTMAX_MAX);
+	  sec = min (EMACS_SECS (t), WAIT_READING_MAX);
 	  nsec = EMACS_NSECS (t);
 	}
     }

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2012-06-23 12:39:23 +0000
+++ src/keyboard.c	2012-06-24 04:11:19 +0000
@@ -3859,7 +3859,7 @@
 	    {
 	      EMACS_SUB_TIME (duration, *end_time, duration);
 	      wait_reading_process_output (min (EMACS_SECS (duration),
-						INTMAX_MAX),
+						WAIT_READING_MAX),
 					   EMACS_NSECS (duration),
 					   -1, 1, Qnil, NULL, 0);
 	    }

=== modified file 'src/lisp.h'
--- src/lisp.h	2012-06-22 21:17:42 +0000
+++ src/lisp.h	2012-06-24 04:11:19 +0000
@@ -3249,6 +3249,14 @@
                                         Lisp_Object,
                                         struct Lisp_Process *,
                                         int);
+/* Max value for the first argument of wait_reading_process_output.  */
+#if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)
+/* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3.
+   The bug merely causes a bogus warning, but the warning is annoying.  */
+# define WAIT_READING_MAX min (TYPE_MAXIMUM (time_t), INTMAX_MAX)
+#else
+# define WAIT_READING_MAX INTMAX_MAX
+#endif
 extern void add_keyboard_wait_descriptor (int);
 extern void delete_keyboard_wait_descriptor (int);
 #ifdef HAVE_GPM

=== modified file 'src/process.c'
--- src/process.c	2012-06-22 21:17:42 +0000
+++ src/process.c	2012-06-24 04:11:19 +0000
@@ -3996,7 +3996,7 @@
 	  if (0 < XFLOAT_DATA (seconds))
 	    {
 	      EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds));
-	      secs = min (EMACS_SECS (t), INTMAX_MAX);
+	      secs = min (EMACS_SECS (t), WAIT_READING_MAX);
 	      nsecs = EMACS_NSECS (t);
 	    }
 	}






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sun, 24 Jun 2012 17:28:02 GMT) Full text and rfc822 format available.

Message #60 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sun, 24 Jun 2012 20:23:44 +0300
> Date: Sat, 23 Jun 2012 15:34:27 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 9000 <at> debbugs.gnu.org
> 
> On 06/23/2012 12:08 PM, Eli Zaretskii wrote:
> > I don't get it: are you trying to fix only the MSVC build?  If not,
> > where are the bits for MinGW?
> 
> Sorry, no, I assumed the problem only occurred with MSVC.
> If it occurs on all Windows platforms, simply remove
> the "#ifdef _MSC_VER" in question.

OK, done as part of trunk revision 108721.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#9000; Package emacs. (Sun, 24 Jun 2012 19:31:02 GMT) Full text and rfc822 format available.

Message #63 received at 9000 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 9000 <at> debbugs.gnu.org
Subject: Re: bug#9000: patch for higher-resolution time stamps
Date: Sun, 24 Jun 2012 22:26:13 +0300
> Date: Sat, 23 Jun 2012 21:31:38 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 9000 <at> debbugs.gnu.org
> 
> I rummaged around our servers and found an old GCC that issues the
> diagnostic, and installed as trunk bzr 108714 a further patch to silence
> those particular warnings without introducing a signedness bug.

Thank you.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 23 Jul 2012 11:24:03 GMT) Full text and rfc822 format available.

This bug report was last modified 11 years and 279 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.