emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/7] C-level support for ns-resolution time stamps


From: Paul Eggert
Subject: [PATCH 5/7] C-level support for ns-resolution time stamps
Date: Fri, 01 Jul 2011 01:15:42 -0700
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110516 Thunderbird/3.1.10

This is the core of the patches; it affects the src subdirectory.

Add support for nanosecond-resolution time stamps.

* Makefile.in (LIB_CLOCK_GETTIME): New macro.
(LIBES): Use it.

* alloc.c (Fgarbage_collect): Port to ns-resolution 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 ns-resolution 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 ns resolution.
Include systime.h, not time.h.
(NONEXISTENT_MODTIME_NSECS, UNKNOWN_MODTIME_NSECS)
(OK_MODTIME_NSECS): New macros.

* dired.c: Include stat-time.h.
(Ffile-attributes): File times now have ns resolution.

* dispextern.h [HAVE_WINDOW_SYSTEM]: Include systime.h.
(struct image): Timestamp now has ns 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 ns-resolution time stamps.

* editfns.c (time_overflow): Now extern.
(hi_time, lo_time): Now return Lisp_Object, for convenience.
Do not assume high order part of time stamp fits in fixnum; it
doesn't, on some hosts.
(Fcurrent_time, get-internal-run-time, make_time, lisp_time_argument)
(float-time, Fformat_time_string, Fcurrent_time_string)
(Fcurrent_time_zone): Accept and generate ns-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 ns_lower_bound.
Report an error if the time is invalid, rather than having the caller
do that.
(Fformat_time_string): Check for string overflow in a place it
was missed.  Allow floating-point year numbers (for really large
years).  Check for time overflow with large years (either integer
or floating point).

* fileio.c: Include <stat-time.h>
(Fcopy_file): Copy ns-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 ns-resolution time stamps.

* gtkutil.c (xg_maybe_add_timer): Port to ns-resolution time stamps.

* image.c (prepare_image_for_display, clear_image_cache)
(lookup_image): Port to ns-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 ns-resolution time stamps.  Do not assume time_t is signed.


* 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): Put ns-resolution time stamps
into the undo buffer.
(Fprimitive_undo): Use them when restoring time stamps.

* w32.c (ltime, U64_TO_LISP_TIME, process_times, emacs_gnutls_pull):
Port to ns-resolution Emacs time stamps.

* 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.
=== modified file 'src/Makefile.in'
--- src/Makefile.in     2011-06-30 14:00:26 +0000
+++ src/Makefile.in     2011-07-01 05:24:22 +0000
@@ -147,6 +147,8 @@
 M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
 M17N_FLT_LIBS = @M17N_FLT_LIBS@

address@hidden@
+
 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 05:24:22 +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 05:24:23 +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-06-27 09:27:44 +0000
+++ src/buffer.c        2011-07-01 05:24:23 +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;
@@ -5860,9 +5860,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 NSEC) indicates that the buffer was previously
+unmodified; (HIGH LOW NSEC) are in the same style as (current-time)
+and are 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-01 05:24:23 +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,14 @@
   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)
+#define OK_MODTIME_NSECS(ns) (0 <= (ns))
+  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-01 05:24:23 +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 three numbers (HIGH LOW NSEC) 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 05:24:23 +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 05:24:23 +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-06-24 21:25:22 +0000
+++ src/editfns.c       2011-07-01 05:24:23 +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,15 +1401,14 @@
 #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.  */
-static EMACS_INT
+/* Return the upper part of the time T (everything but the bottom 16 bits).  */
+static Lisp_Object
 hi_time (time_t t)
 {
   time_t hi = t >> 16;
@@ -1418,59 +1416,53 @@
   /* 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)
-         || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16
-         || MOST_NEGATIVE_FIXNUM <= hi)
-        && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM
-            || hi <= MOST_POSITIVE_FIXNUM)))
-    time_overflow ();
-
-  return hi;
+  if ((! TYPE_SIGNED (time_t)
+       || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16
+       || MOST_NEGATIVE_FIXNUM <= hi)
+      && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM
+         || hi <= MOST_POSITIVE_FIXNUM))
+    return make_number (hi);
+  else
+    return make_float (hi);
 }

 /* Return the bottom 16 bits of the time T.  */
-static EMACS_INT
+static Lisp_Object
 lo_time (time_t t)
 {
-  return t & ((1 << 16) - 1);
+  return make_number (t & ((1 << 16) - 1));
 }

 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 (HIGH LOW NSEC).  HIGH has the most
+significant bits of the seconds, while LOW has the least significant
+16 bits.  NSEC gives the nanosecond count.  All three values are integers,
+except that the HIGH and NSEC may be floating-point on systems that
+cannot represent large-enough integers.  */)
   (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 NSEC), 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 +1476,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,86 +1488,176 @@
 }
 

-/* 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 (hi_time (t), Fcons (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
+   slightly negative nanosecond count.  */
+Lisp_Object
+make_lisp_time (EMACS_TIME t)
+{
+  int ns = EMACS_NSECS (t);
+  int frac = ns;
+  Lisp_Object fraction =
+    (MOST_POSITIVE_FIXNUM < EMACS_TIME_RESOLUTION && MOST_POSITIVE_FIXNUM < 
frac
+     ? make_float (frac)
+     : make_number (frac));
+  return make_time_tail (EMACS_SECS (t), list1 (fraction));
 }

 /* 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, *PFRAC to its components; do not check their values.
    Return nonzero if successful.  */
+static int
+disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
+                      Lisp_Object *plow, Lisp_Object *pfrac)
+{
+  if (CONSP (specified_time))
+    {
+      Lisp_Object low = XCDR (specified_time);
+      Lisp_Object frac = make_number (0);
+      if (CONSP (low))
+       {
+         Lisp_Object low_tail = XCDR (low);
+         low = XCAR (low);
+         if (CONSP (low_tail))
+           frac = XCAR (low_tail);
+         else if (!NILP (low_tail))
+           frac = low_tail;
+       }
+
+      *phigh = XCAR (specified_time);
+      *plow = low;
+      *pfrac = frac;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* From the time components HIGH, LOW, and FRAC taken from a Lisp list,
+   and a NS_LOWER_BOUND threshold giving the minimum allowed value for FRAC,
+   generate the corresponding EMACS_TIME value *RESULT.  Return nonzero
+   if successful.  */
 int
-lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec)
+decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object frac,
+                       int ns_lower_bound, EMACS_TIME *result)
 {
-  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 (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.  */
+  time_t s;
+  int ns;
+
+  /* Check for overflow, helping the compiler for common cases
+     where no runtime check is needed, and taking care not to
+     convert negative to unsigned before comparison.  */
+  if (INTEGERP (high))
+    {
+      EMACS_INT h = XINT (high);
       if (! ((TYPE_SIGNED (time_t)
              ? (TIME_T_MIN >> 16 <= MOST_NEGATIVE_FIXNUM
-                || TIME_T_MIN >> 16 <= hi)
-             : 0 <= hi)
+                || TIME_T_MIN >> 16 <= h)
+             : 0 <= h)
             && (MOST_POSITIVE_FIXNUM <= TIME_T_MAX >> 16
-                || hi <= TIME_T_MAX >> 16)))
-       return 0;
-
-      *result = (hi << 16) + (XINT (low) & 0xffff);
-      return 1;
-    }
-}
+                || h <= TIME_T_MAX >> 16)))
+       return 0;
+      s = h;
+    }
+  else if (FLOATP (high))
+    {
+      double h = XFLOAT_DATA (high);
+      if (! (TIME_T_MIN >> 16 <= h && h < (TIME_T_MAX >> 16) + 1))
+       return 0;
+      s = h;
+      if (! (s == h))
+       return 0;
+    }
+  else
+    return 0;
+
+  if (! (INTEGERP (low) && 0 <= XINT (low) && XINT (low) < (1 << 16)))
+    return 0;
+  s = (s << 16) + XINT (low);
+
+  if (INTEGERP (frac))
+    {
+      EMACS_INT f = XINT (frac);
+      if (! (ns_lower_bound <= f && f < EMACS_TIME_RESOLUTION))
+       return 0;
+      ns = f;
+    }
+  else if (FLOATP (frac))
+    {
+      double f = XFLOAT_DATA (frac);
+      if (! (ns_lower_bound <= f && f < EMACS_TIME_RESOLUTION))
+       return 0;
+      ns = f;
+    }
+  else
+    return 0;
+
+  EMACS_SET_SECS_NSECS (*result, s, ns);
+  return 1;
+}
+
+/* Decode a Lisp list SPECIFIED_TIME that represents a time.
+   If SPECIFIED_TIME is nil, use the current time.
+   Return seconds since the Epoch.
+   NS_LOWER_BOUND gives the lowest allowable nanosecond count.
+   If NS_LOWER_BOUND < 0, the specified time may be invalid, and it's OK to
+   generate a list with the same invalid nanosecond count.
+   Signal an error if unsuccessful.  */
+EMACS_TIME
+lisp_time_argument (Lisp_Object specified_time, int ns_lower_bound)
+{
+  EMACS_TIME t;
+  if (NILP (specified_time))
+    EMACS_GET_TIME (t);
+  else
+    {
+      Lisp_Object high, low, frac;
+      if (! (disassemble_lisp_time (specified_time, &high, &low, &frac)
+            && decode_time_components (high, low, frac, ns_lower_bound, &t)))
+       error ("Invalid time specification");
+    }
+  return t;
+}
+
+/* Like lisp_time_argument, except decode only the seconds part,
+   and do not check the nanoseconds part.  */
+static time_t
+lisp_seconds_argument (Lisp_Object specified_time)
+{
+  if (NILP (specified_time))
+    return time (NULL);
+  else
+    {
+      Lisp_Object high, low, frac;
+      EMACS_TIME t;
+      if (! (disassemble_lisp_time (specified_time, &high, &low, &frac)
+            && decode_time_components (high, low, make_number (0), 0, &t)))
+       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
+(HIGH LOW) or (HIGH LOW NSEC).  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.

@@ -1586,13 +1666,8 @@
 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);
+  EMACS_TIME t = lisp_time_argument (specified_time, 0);
+  return make_float (EMACS_TIME_TO_DOUBLE (t));
 }

 /* Write information into buffer S of size MAXSIZE, according to the
@@ -1647,7 +1722,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 NSEC), 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,28 +1774,26 @@
 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;
-  int size;
-  int usec;
+  EMACS_TIME t;
+  ptrdiff_t size;
   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);

   /* This is probably enough.  */
-  size = SBYTES (format_string) * 6 + 50;
+  size = SBYTES (format_string);
+  if (size <= (STRING_BYTES_BOUND - 50) / 6)
+    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 ();
@@ -1736,7 +1809,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),
@@ -1747,8 +1820,10 @@
       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 ();
       size = result + 1;
     }
 }
@@ -1762,7 +1837,7 @@
 and 60; SEC is 60 for a leap second, which only some operating systems
 support.  MINUTE is an integer between 0 and 59.  HOUR is an integer
 between 0 and 23.  DAY is an integer between 1 and 31.  MONTH is an
-integer between 1 and 12.  YEAR is an integer indicating the
+integer between 1 and 12.  YEAR is a number indicating the
 four-digit year.  DOW is the day of week, an integer between 0 and 6,
 where 0 is Sunday.  DST is t if daylight saving time is in effect,
 otherwise nil.  ZONE is an integer indicating the number of seconds
@@ -1770,29 +1845,29 @@
 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;
-  if (! (decoded_time
-        && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= decoded_time->tm_year
-        && decoded_time->tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE))
+  if (! decoded_time)
     time_overflow ();
   XSETFASTINT (list_args[0], decoded_time->tm_sec);
   XSETFASTINT (list_args[1], decoded_time->tm_min);
   XSETFASTINT (list_args[2], decoded_time->tm_hour);
   XSETFASTINT (list_args[3], decoded_time->tm_mday);
   XSETFASTINT (list_args[4], decoded_time->tm_mon + 1);
-  /* On 64-bit machines an int is narrower than EMACS_INT, thus the
-     cast below avoids overflow in int arithmetics.  */
-  XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) decoded_time->tm_year);
+
+  if (decoded_time
+      && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= decoded_time->tm_year
+      && decoded_time->tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)
+    XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) decoded_time->tm_year);
+  else
+    list_args[5] = make_float (TM_YEAR_BASE + (double) decoded_time->tm_year);
+
   XSETFASTINT (list_args[6], decoded_time->tm_wday);
   list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;

@@ -1855,7 +1930,17 @@
   tm.tm_hour = check_tm_member (args[2], 0);
   tm.tm_mday = check_tm_member (args[3], 0);
   tm.tm_mon  = check_tm_member (args[4], 1);
-  tm.tm_year = check_tm_member (args[5], TM_YEAR_BASE);
+  if (FLOATP (args[5]))
+    {
+      double n = XFLOAT_DATA (args[5]) - TM_YEAR_BASE;
+      if (! (INT_MIN <= n && n < INT_MAX + 1.0))
+       time_overflow ();
+      tm.tm_year = n;
+      if (tm.tm_year != n)
+       time_overflow ();
+    }
+  else
+    tm.tm_year = check_tm_member (args[5], TM_YEAR_BASE);
   tm.tm_isdst = -1;

   if (CONSP (zone))
@@ -1925,13 +2010,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.  */
@@ -1987,23 +2069,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-06-24 21:25:22 +0000
+++ src/fileio.c        2011-07-01 05:24:23 +0000
@@ -76,6 +76,7 @@
 #endif

 #include "systime.h"
+#include <stat-time.h>

 #ifdef HPUX
 #include <netio.h>
@@ -1873,7 +1874,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);
@@ -1974,24 +1975,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
@@ -2932,11 +2930,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));

@@ -2949,12 +2943,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;
@@ -4055,7 +4044,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;
        }
@@ -4220,7 +4209,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));
@@ -4655,7 +4644,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;
     }

@@ -4932,6 +4921,7 @@
   struct stat st;
   Lisp_Object handler;
   Lisp_Object filename;
+  EMACS_TIME mtime, diff, one_second;

   if (NILP (buf))
     b = current_buffer;
@@ -4942,7 +4932,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.  */
@@ -4953,20 +4943,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;
@@ -4979,7 +4974,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;
 }
@@ -4987,15 +4982,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 NANOSECONDS), 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,
@@ -5005,12 +5000,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 NSEC) or (HIGH LOW) or (HIGH . LOW).  */)
   (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
@@ -5032,7 +5027,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 05:24:23 +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 05:24:23 +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-06-20 06:07:16 +0000
+++ src/keyboard.c      2011-07-01 05:24:23 +0000
@@ -2003,12 +2003,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);
        }
@@ -2076,7 +2077,7 @@
 bind_polling_period (int n)
 {
 #ifdef POLL_FOR_INPUT
-  int new = polling_period;
+  EMACS_INT new = polling_period;

   if (n > new)
     new = n;
@@ -2206,7 +2207,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;
@@ -2257,7 +2258,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;
@@ -3758,7 +3759,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;
@@ -3831,8 +3832,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);
            }
        }
@@ -4194,7 +4196,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 @@
 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.  */
@@ -4227,7 +4229,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;
@@ -4258,17 +4260,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;
@@ -4286,8 +4287,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))
@@ -4296,113 +4299,102 @@
       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);
+         if (!VECTORP (timer) || ASIZE (timer) != 8)
+           {
+             timers = XCDR (timers);
+             continue;
+           }
          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 (! (NILP (vector[0])
+                && decode_time_components (vector[1], vector[2], vector[3],
+                                           0, &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);
+         if (!VECTORP (idle_timer) || ASIZE (idle_timer) != 8)
+           {
+             idle_timers = XCDR (idle_timers);
+             continue;
+           }
          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 (! (NILP (vector[0])
+                && decode_time_components (vector[1], vector[2], vector[3],
+                                           0, &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 ();
@@ -4449,7 +4441,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.  */

@@ -4462,33 +4454,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 three numbers (HIGH LOW NSEC)
+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;
@@ -10779,7 +10767,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;

@@ -11382,7 +11370,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 05:24:23 +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-06-24 21:25:22 +0000
+++ src/lread.c 2011-07-01 05:24:23 +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 05:24:23 +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 05:24:23 +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 05:24:23 +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-06-26 03:40:40 +0000
+++ src/process.c       2011-07-01 05:24:23 +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,19 @@
  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 the (HIGH LOW NSEC) format
+ stime   -- system time used by the process, in the (HIGH LOW NSEC) format
+ time    -- sum of utime and stime, in the (HIGH LOW NSEC) format
+ cutime  -- user time used by the process and its children, (HIGH LOW NSEC)
+ cstime  -- system time used by the process and its children, (HIGH LOW NSEC)
+ ctime   -- sum of cutime and cstime, in the (HIGH LOW NSEC) format
  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, in the (HIGH LOW NSEC) format
  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 NSEC) 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 05:24:23 +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 05:24:23 +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 05:24:23 +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-01 05:24:23 +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, int,
+                                  EMACS_TIME *);
+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 05:24:23 +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-01 05:24:23 +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,10 @@
              cdr = XCDR (next);
              if (EQ (car, Qt))
                {
-                 /* Element (t high . low) records previous modtime.  */
+                 /* Element (t . TIME) records previous modtime.  */
                  struct buffer *base_buffer = current_buffer;
-                 time_t mod_time;
-                 CONS_TO_INTEGER (cdr, time_t, mod_time);
+                 EMACS_TIME mod_time =
+                   lisp_time_argument (cdr, UNKNOWN_MODTIME_NSECS);

                  if (current_buffer->base_buffer)
                    base_buffer = current_buffer->base_buffer;
@@ -508,7 +508,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-01 05:24:23 +0000
@@ -4005,14 +4005,14 @@
 }

 static Lisp_Object
-ltime (long time_sec, long time_usec)
+ltime (long time_sec, long time_100nsec)
 {
   return list3 (make_number ((time_sec >> 16) & 0xffff),
                make_number (time_sec & 0xffff),
-               make_number (time_usec));
+               make_number (time_100nsec * 100));
 }

-#define U64_TO_LISP_TIME(time) ltime ((time) / 1000000L, (time) % 1000000L)
+#define U64_TO_LISP_TIME(time) ltime ((time) / 10000000L, (time) % 10000000L)

 static int
 process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
@@ -4031,11 +4031,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 +4042,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 +6196,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 +6212,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 05:24:23 +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-04-16 07:57:31 +0000
+++ src/xgselect.c      2011-07-01 05:24:23 +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 05:24:23 +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 05:24:23 +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 05:24:23 +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 05:24:23 +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;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]