use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / sysdep.c
index 11a6f4a..e8b0057 100644 (file)
@@ -1,5 +1,5 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985-1988, 1993-1995, 1999-2013 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1999-2014 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -19,8 +19,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define SYSTIME_INLINE EXTERN_INLINE
-
 #include <execinfo.h>
 #include "sysstdio.h"
 #ifdef HAVE_PWD_H
@@ -130,7 +128,7 @@ static const int baud_convert[] =
 /* Return the current working directory.  Returns NULL on errors.
    Any other returned value must be freed with free. This is used
    only when get_current_dir_name is not defined on the system.  */
-char*
+char *
 get_current_dir_name (void)
 {
   char *buf;
@@ -224,7 +222,9 @@ discard_tty_input (void)
 void
 stuff_char (char c)
 {
-  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
+  if (! (FRAMEP (selected_frame)
+        && FRAME_LIVE_P (XFRAME (selected_frame))
+        && FRAME_TERMCAP_P (XFRAME (selected_frame))))
     return;
 
 /* Should perhaps error if in batch mode */
@@ -257,7 +257,7 @@ init_baud_rate (int fd)
 #endif /* not DOS_NT */
     }
 
-  baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
+  baud_rate = (emacs_ospeed < ARRAYELTS (baud_convert)
               ? baud_convert[emacs_ospeed] : 9600);
   if (baud_rate == 0)
     baud_rate = 1200;
@@ -306,7 +306,7 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
   /* If successful and status is requested, tell wait_reading_process_output
      that it needs to wake up and look around.  */
   if (pid && status && input_available_clear_time)
-    *input_available_clear_time = make_emacs_time (0, 0);
+    *input_available_clear_time = make_timespec (0, 0);
 
   return pid;
 }
@@ -337,16 +337,6 @@ child_status_changed (pid_t child, int *status, int options)
   return get_child_status (child, status, WNOHANG | options, 0);
 }
 
-/*
- *     flush any pending output
- *      (may flush input as well; it does not matter the way we use it)
- */
-
-void
-flush_pending_output (int channel)
-{
-  /* FIXME: maybe this function should be removed */
-}
 \f
 /*  Set up the terminal at the other end of a pseudo-terminal that
     we will be controlling an inferior through.
@@ -476,15 +466,29 @@ sys_subshell (void)
 {
 #ifdef DOS_NT  /* Demacs 1.1.2 91/10/20 Manabu Higashida */
   int st;
+#ifdef MSDOS
   char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
+#else
+  char oldwd[MAX_UTF8_PATH];
+#endif
 #endif
   pid_t pid;
   int status;
   struct save_signal saved_handlers[5];
-  Lisp_Object dir;
-  unsigned char *volatile str_volatile = 0;
-  unsigned char *str;
-  int len;
+  char *str = SSDATA (encode_current_directory ());
+
+#ifdef DOS_NT
+  pid = 0;
+#else
+  {
+    char *volatile str_volatile = str;
+    pid = vfork ();
+    str = str_volatile;
+  }
+#endif
+
+  if (pid < 0)
+    error ("Can't spawn subshell");
 
   saved_handlers[0].code = SIGINT;
   saved_handlers[1].code = SIGQUIT;
@@ -496,31 +500,8 @@ sys_subshell (void)
   saved_handlers[3].code = 0;
 #endif
 
-  /* Mentioning current_buffer->buffer would mean including buffer.h,
-     which somehow wedges the hp compiler.  So instead...  */
-
-  dir = intern ("default-directory");
-  if (NILP (Fboundp (dir)))
-    goto xyzzy;
-  dir = Fsymbol_value (dir);
-  if (!STRINGP (dir))
-    goto xyzzy;
-
-  dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
-  str_volatile = str = alloca (SCHARS (dir) + 2);
-  len = SCHARS (dir);
-  memcpy (str, SDATA (dir), len);
-  if (str[len - 1] != '/') str[len++] = '/';
-  str[len] = 0;
- xyzzy:
-
 #ifdef DOS_NT
-  pid = 0;
   save_signal_handlers (saved_handlers);
-#else
-  pid = vfork ();
-  if (pid == -1)
-    error ("Can't spawn subshell");
 #endif
 
   if (pid == 0)
@@ -538,11 +519,10 @@ sys_subshell (void)
        sh = "sh";
 
       /* Use our buffer's default directory for the subshell.  */
-      str = str_volatile;
-      if (str && chdir ((char *) str) != 0)
+      if (chdir (str) != 0)
        {
 #ifndef DOS_NT
-         emacs_perror ((char *) str);
+         emacs_perror (str);
          _exit (EXIT_CANCELED);
 #endif
        }
@@ -556,8 +536,6 @@ sys_subshell (void)
        if (epwd)
          {
            strcpy (old_pwd, epwd);
-           if (str[len - 1] == '/')
-             str[len - 1] = '\0';
            setenv ("PWD", str, 1);
          }
        st = system (sh);
@@ -614,7 +592,7 @@ restore_signal_handlers (struct save_signal *saved_handlers)
 }
 \f
 #ifdef USABLE_SIGIO
-static int old_fcntl_flags[MAXDESC];
+static int old_fcntl_flags[FD_SETSIZE];
 #endif
 
 void
@@ -627,6 +605,7 @@ init_sigio (int fd)
 #endif
 }
 
+#ifndef DOS_NT
 static void
 reset_sigio (int fd)
 {
@@ -634,6 +613,7 @@ reset_sigio (int fd)
   fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
 #endif
 }
+#endif
 
 void
 request_sigio (void)
@@ -681,7 +661,29 @@ ignore_sigio (void)
   signal (SIGIO, SIG_IGN);
 #endif
 }
+\f
+#ifndef MSDOS
+/* Block SIGCHLD.  */
 
+void
+block_child_signal (sigset_t *oldset)
+{
+  sigset_t blocked;
+  sigemptyset (&blocked);
+  sigaddset (&blocked, SIGCHLD);
+  sigaddset (&blocked, SIGINT);
+  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
+}
+
+/* Unblock SIGCHLD.  */
+
+void
+unblock_child_signal (sigset_t const *oldset)
+{
+  pthread_sigmask (SIG_SETMASK, oldset, 0);
+}
+
+#endif /* !MSDOS */
 \f
 /* Saving and restoring the process group of Emacs's terminal.  */
 
@@ -716,21 +718,21 @@ init_foreground_group (void)
 /* Block and unblock SIGTTOU.  */
 
 void
-block_tty_out_signal (void)
+block_tty_out_signal (sigset_t *oldset)
 {
 #ifdef SIGTTOU
   sigset_t blocked;
   sigemptyset (&blocked);
   sigaddset (&blocked, SIGTTOU);
-  pthread_sigmask (SIG_BLOCK, &blocked, 0);
+  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
 #endif
 }
 
 void
-unblock_tty_out_signal (void)
+unblock_tty_out_signal (sigset_t const *oldset)
 {
 #ifdef SIGTTOU
-  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  pthread_sigmask (SIG_SETMASK, oldset, 0);
 #endif
 }
 
@@ -745,10 +747,11 @@ static void
 tcsetpgrp_without_stopping (int fd, pid_t pgid)
 {
 #ifdef SIGTTOU
+  sigset_t oldset;
   block_input ();
-  block_tty_out_signal ();
+  block_tty_out_signal (&oldset);
   tcsetpgrp (fd, pgid);
-  unblock_tty_out_signal ();
+  unblock_tty_out_signal (&oldset);
   unblock_input ();
 #endif
 }
@@ -843,7 +846,7 @@ emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp)
 \f
 
 #ifdef F_SETOWN
-static int old_fcntl_owner[MAXDESC];
+static int old_fcntl_owner[FD_SETSIZE];
 #endif /* F_SETOWN */
 
 /* This may also be defined in stdio,
@@ -1196,7 +1199,8 @@ get_tty_size (int fd, int *widthp, int *heightp)
 }
 
 /* Set the logical window size associated with descriptor FD
-   to HEIGHT and WIDTH.  This is used mainly with ptys.  */
+   to HEIGHT and WIDTH.  This is used mainly with ptys.
+   Return a negative value on failure.  */
 
 int
 set_window_size (int fd, int height, int width)
@@ -1208,10 +1212,7 @@ set_window_size (int fd, int height, int width)
   size.ws_row = height;
   size.ws_col = width;
 
-  if (ioctl (fd, TIOCSWINSZ, &size) == -1)
-    return 0; /* error */
-  else
-    return 1;
+  return ioctl (fd, TIOCSWINSZ, &size);
 
 #else
 #ifdef TIOCSSIZE
@@ -1221,10 +1222,7 @@ set_window_size (int fd, int height, int width)
   size.ts_lines = height;
   size.ts_cols = width;
 
-  if (ioctl (fd, TIOCGSIZE, &size) == -1)
-    return 0;
-  else
-    return 1;
+  return ioctl (fd, TIOCGSIZE, &size);
 #else
   return -1;
 #endif /* not SunOS-style */
@@ -1274,7 +1272,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
       int i;
       tty_turn_off_insert (tty_out);
 
-      for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
+      for (i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++)
         {
           fputc (' ', tty_out->output);
         }
@@ -1535,7 +1533,9 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
   /* When handling a signal, block nonfatal system signals that are caught
      by Emacs.  This makes race conditions less likely.  */
   sigaddset (&action->sa_mask, SIGALRM);
+#ifdef SIGCHLD
   sigaddset (&action->sa_mask, SIGCHLD);
+#endif
 #ifdef SIGDANGER
   sigaddset (&action->sa_mask, SIGDANGER);
 #endif
@@ -1554,9 +1554,6 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
 #endif
     }
 
-  if (! IEEE_FLOATING_POINT)
-    sigaddset (&action->sa_mask, SIGFPE);
-
   action->sa_handler = handler;
   action->sa_flags = emacs_sigaction_flags ();
 }
@@ -1740,7 +1737,9 @@ init_signals (bool dumping)
 # ifdef SIGBUS
       sys_siglist[SIGBUS] = "Bus error";
 # endif
+# ifdef SIGCHLD
       sys_siglist[SIGCHLD] = "Child status changed";
+# endif
 # ifdef SIGCONT
       sys_siglist[SIGCONT] = "Continued";
 # endif
@@ -1951,9 +1950,6 @@ init_signals (bool dumping)
 #ifdef SIGVTALRM
   sigaction (SIGVTALRM, &process_fatal_action, 0);
 #endif
-#ifdef SIGXCPU
-  sigaction (SIGXCPU, &process_fatal_action, 0);
-#endif
 #ifdef SIGXFSZ
   sigaction (SIGXFSZ, &process_fatal_action, 0);
 #endif
@@ -2052,8 +2048,8 @@ seed_random (void *seed, ptrdiff_t seed_size)
 void
 init_random (void)
 {
-  EMACS_TIME t = current_emacs_time ();
-  uintmax_t v = getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t);
+  struct timespec t = current_timespec ();
+  uintmax_t v = getpid () ^ t.tv_sec ^ t.tv_nsec;
   seed_random (&v, sizeof v);
 }
 
@@ -2211,6 +2207,9 @@ emacs_fopen (char const *file, char const *mode)
 int
 emacs_pipe (int fd[2])
 {
+#ifdef MSDOS
+  return pipe (fd);
+#else  /* !MSDOS */
   int result = pipe2 (fd, O_CLOEXEC);
   if (! O_CLOEXEC && result == 0)
     {
@@ -2218,6 +2217,7 @@ emacs_pipe (int fd[2])
       fcntl (fd[1], F_SETFD, FD_CLOEXEC);
     }
   return result;
+#endif /* !MSDOS */
 }
 
 /* Approximate posix_close and POSIX_CLOSE_RESTART well enough for Emacs.
@@ -2290,9 +2290,9 @@ emacs_close (int fd)
    Return the number of bytes read, which might be less than NBYTE.
    On error, set errno and return -1.  */
 ptrdiff_t
-emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
+emacs_read (int fildes, void *buf, ptrdiff_t nbyte)
 {
-  register ssize_t rtnval;
+  ssize_t rtnval;
 
   /* There is no need to check against MAX_RW_COUNT, since no caller ever
      passes a size that large to emacs_read.  */
@@ -2343,14 +2343,14 @@ emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte,
    interrupted or if a partial write occurs.  Return the number of
    bytes written, setting errno if this is less than NBYTE.  */
 ptrdiff_t
-emacs_write (int fildes, char const *buf, ptrdiff_t nbyte)
+emacs_write (int fildes, void const *buf, ptrdiff_t nbyte)
 {
   return emacs_full_write (fildes, buf, nbyte, 0);
 }
 
 /* Like emacs_write, but also process pending signals if interrupted.  */
 ptrdiff_t
-emacs_write_sig (int fildes, char const *buf, ptrdiff_t nbyte)
+emacs_write_sig (int fildes, void const *buf, ptrdiff_t nbyte)
 {
   return emacs_full_write (fildes, buf, nbyte, 1);
 }
@@ -2388,7 +2388,7 @@ emacs_perror (char const *message)
    Use the least timeval not less than T.
    Return an extremal value if the result would overflow.  */
 struct timeval
-make_timeval (EMACS_TIME t)
+make_timeval (struct timespec t)
 {
   struct timeval tv;
   tv.tv_sec = t.tv_sec;
@@ -2415,7 +2415,7 @@ make_timeval (EMACS_TIME t)
    If FD is nonnegative, then FILE can be NULL.  */
 int
 set_file_times (int fd, const char *filename,
-               EMACS_TIME atime, EMACS_TIME mtime)
+               struct timespec atime, struct timespec mtime)
 {
   struct timespec timespec[2];
   timespec[0] = atime;
@@ -2485,7 +2485,7 @@ serial_configure (struct Lisp_Process *p,
   Lisp_Object childp2 = Qnil;
   Lisp_Object tem = Qnil;
   struct termios attr;
-  int err = -1;
+  int err;
   char summary[4] = "???"; /* This usually becomes "8N1".  */
 
   childp2 = Fcopy_sequence (p->childp);
@@ -2732,7 +2732,7 @@ list_system_processes (void)
 #endif /* !defined (WINDOWSNT) */
 
 #if defined GNU_LINUX && defined HAVE_LONG_LONG_INT
-static EMACS_TIME
+static struct timespec
 time_from_jiffies (unsigned long long tval, long hz)
 {
   unsigned long long s = tval / hz;
@@ -2741,34 +2741,34 @@ time_from_jiffies (unsigned long long tval, long 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;
+  if (LONG_MAX - 1 <= ULLONG_MAX / TIMESPEC_RESOLUTION
+      || frac <= ULLONG_MAX / TIMESPEC_RESOLUTION)
+    ns = frac * TIMESPEC_RESOLUTION / hz;
   else
     {
       /* This is reachable only in the unlikely case that HZ * HZ
         exceeds ULLONG_MAX.  It calculates an approximation that is
         guaranteed to be in range.  */
-      long hz_per_ns = (hz / EMACS_TIME_RESOLUTION
-                       + (hz % EMACS_TIME_RESOLUTION != 0));
+      long hz_per_ns = (hz / TIMESPEC_RESOLUTION
+                       + (hz % TIMESPEC_RESOLUTION != 0));
       ns = frac / hz_per_ns;
     }
 
-  return make_emacs_time (s, ns);
+  return make_timespec (s, ns);
 }
 
 static Lisp_Object
 ltime_from_jiffies (unsigned long long tval, long hz)
 {
-  EMACS_TIME t = time_from_jiffies (tval, hz);
+  struct timespec t = time_from_jiffies (tval, hz);
   return make_lisp_time (t);
 }
 
-static EMACS_TIME
+static struct timespec
 get_up_time (void)
 {
   FILE *fup;
-  EMACS_TIME up = make_emacs_time (0, 0);
+  struct timespec up = make_timespec (0, 0);
 
   block_input ();
   fup = emacs_fopen ("/proc/uptime", "r");
@@ -2786,18 +2786,18 @@ get_up_time (void)
          if (TYPE_MAXIMUM (time_t) < upsec)
            {
              upsec = TYPE_MAXIMUM (time_t);
-             upfrac = EMACS_TIME_RESOLUTION - 1;
+             upfrac = TIMESPEC_RESOLUTION - 1;
            }
          else
            {
              int upfraclen = upfrac_end - upfrac_start;
-             for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++)
+             for (; upfraclen < LOG10_TIMESPEC_RESOLUTION; upfraclen++)
                upfrac *= 10;
-             for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--)
+             for (; LOG10_TIMESPEC_RESOLUTION < upfraclen; upfraclen--)
                upfrac /= 10;
-             upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
+             upfrac = min (upfrac, TIMESPEC_RESOLUTION - 1);
            }
-         up = make_emacs_time (upsec, upfrac);
+         up = make_timespec (upsec, upfrac);
        }
       fclose (fup);
     }
@@ -2852,29 +2852,41 @@ procfs_ttyname (int rdev)
   return build_string (name);
 }
 
-static unsigned long
+static uintmax_t
 procfs_get_total_memory (void)
 {
   FILE *fmem;
-  unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
+  uintmax_t retval = 2 * 1024 * 1024; /* default: 2 GiB */
+  int c;
 
   block_input ();
   fmem = emacs_fopen ("/proc/meminfo", "r");
 
   if (fmem)
     {
-      unsigned long entry_value;
-      char entry_name[20];     /* the longest I saw is 13+1 */
+      uintmax_t entry_value;
+      bool done;
+
+      do
+       switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value))
+         {
+         case 1:
+           retval = entry_value;
+           done = 1;
+           break;
+
+         case 0:
+           while ((c = getc (fmem)) != EOF && c != '\n')
+             continue;
+           done = c == EOF;
+           break;
+
+         default:
+           done = 1;
+           break;
+         }
+      while (!done);
 
-      while (!feof (fmem) && !ferror (fmem))
-       {
-         if (fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) >= 2
-             && strcmp (entry_name, "MemTotal:") == 0)
-           {
-             retval = entry_value;
-             break;
-           }
-       }
       fclose (fmem);
     }
   unblock_input ();
@@ -2906,7 +2918,7 @@ system_process_attributes (Lisp_Object pid)
   unsigned long long u_time, s_time, cutime, cstime, start;
   long priority, niceness, rss;
   unsigned long minflt, majflt, cminflt, cmajflt, vsize;
-  EMACS_TIME tnow, tstart, tboot, telapsed, us_time;
+  struct timespec tnow, tstart, tboot, telapsed, us_time;
   double pcpu, pmem;
   Lisp_Object attrs = Qnil;
   Lisp_Object cmd_str, decoded_cmd;
@@ -2938,7 +2950,7 @@ system_process_attributes (Lisp_Object pid)
   if (gr)
     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
 
-  count = SPECPDL_INDEX ();
+  dynwind_begin ();
   strcpy (fn, procfn);
   procfn_end = fn + strlen (fn);
   strcpy (procfn_end, "/stat");
@@ -3027,20 +3039,19 @@ system_process_attributes (Lisp_Object pid)
          attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs);
          attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount)),
                         attrs);
-         tnow = current_emacs_time ();
+         tnow = current_timespec ();
          telapsed = get_up_time ();
-         tboot = sub_emacs_time (tnow, telapsed);
+         tboot = timespec_sub (tnow, telapsed);
          tstart = time_from_jiffies (start, clocks_per_sec);
-         tstart = add_emacs_time (tboot, tstart);
+         tstart = timespec_add (tboot, tstart);
          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);
-         telapsed = sub_emacs_time (tnow, tstart);
+         telapsed = timespec_sub (tnow, tstart);
          attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
          us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
-         pcpu = (EMACS_TIME_TO_DOUBLE (us_time)
-                 / EMACS_TIME_TO_DOUBLE (telapsed));
+         pcpu = timespectod (us_time) / timespectod (telapsed);
          if (pcpu > 1.0)
            pcpu = 1.0;
          attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
@@ -3050,7 +3061,7 @@ system_process_attributes (Lisp_Object pid)
          attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
        }
     }
-  unbind_to (count, Qnil);
+  dynwind_end ();
 
   /* args */
   strcpy (procfn_end, "/cmdline");
@@ -3058,14 +3069,13 @@ system_process_attributes (Lisp_Object pid)
   if (fd >= 0)
     {
       ptrdiff_t readsize, nread_incr;
+      dynwind_begin ();
       record_unwind_protect_int (close_file_unwind, fd);
-      record_unwind_protect_nothing ();
       nread = cmdline_size = 0;
 
       do
        {
          cmdline = xpalloc (cmdline, &cmdline_size, 2, STRING_BYTES_BOUND, 1);
-         set_unwind_protect_ptr (count + 1, xfree, cmdline);
 
          /* Leave room even if every byte needs escaping below.  */
          readsize = (cmdline_size >> 1) - nread;
@@ -3099,14 +3109,13 @@ system_process_attributes (Lisp_Object pid)
          nread = cmdsize + 2;
          cmdline_size = nread + 1;
          q = cmdline = xrealloc (cmdline, cmdline_size);
-         set_unwind_protect_ptr (count + 1, xfree, cmdline);
          sprintf (cmdline, "[%.*s]", cmdsize, cmd);
        }
       /* Command line is encoded in locale-coding-system; decode it.  */
       cmd_str = make_unibyte_string (q, nread);
       decoded_cmd = code_convert_string_norecord (cmd_str,
                                                  Vlocale_coding_system, 0);
-      unbind_to (count, Qnil);
+      dynwind_end ();
       attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
     }
 
@@ -3177,7 +3186,7 @@ system_process_attributes (Lisp_Object pid)
   if (gr)
     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
 
-  count = SPECPDL_INDEX ();
+  dynwind_begin ();
   strcpy (fn, procfn);
   procfn_end = fn + strlen (fn);
   strcpy (procfn_end, "/psinfo");
@@ -3243,33 +3252,31 @@ system_process_attributes (Lisp_Object pid)
                     attrs);
 
       decoded_cmd = (code_convert_string_norecord
-                    (make_unibyte_string (pinfo.pr_fname,
-                                          strlen (pinfo.pr_fname)),
+                    (build_unibyte_string (pinfo.pr_fname),
                      Vlocale_coding_system, 0));
       attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
       decoded_cmd = (code_convert_string_norecord
-                    (make_unibyte_string (pinfo.pr_psargs,
-                                          strlen (pinfo.pr_psargs)),
+                    (build_unibyte_string (pinfo.pr_psargs),
                      Vlocale_coding_system, 0));
       attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
     }
-  unbind_to (count, Qnil);
+  dynwind_end ();
   UNGCPRO;
   return attrs;
 }
 
 #elif defined __FreeBSD__
 
-static EMACS_TIME
-timeval_to_EMACS_TIME (struct timeval t)
+static struct timespec
+timeval_to_timespec (struct timeval t)
 {
-  return make_emacs_time (t.tv_sec, t.tv_usec * 1000);
+  return make_timespec (t.tv_sec, t.tv_usec * 1000);
 }
 
 static Lisp_Object
 make_lisp_timeval (struct timeval t)
 {
-  return make_lisp_time (timeval_to_EMACS_TIME (t));
+  return make_lisp_time (timeval_to_timespec (t));
 }
 
 Lisp_Object
@@ -3277,14 +3284,14 @@ system_process_attributes (Lisp_Object pid)
 {
   int proc_id;
   int pagesize = getpagesize ();
-  int npages;
+  unsigned long npages;
   int fscale;
   struct passwd *pw;
   struct group  *gr;
   char *ttyname;
   size_t len;
   char args[MAXPATHLEN];
-  EMACS_TIME t, now;
+  struct timespec t, now;
 
   int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
   struct kinfo_proc proc;
@@ -3319,9 +3326,9 @@ system_process_attributes (Lisp_Object pid)
   if (gr)
     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
 
-  decoded_comm = code_convert_string_norecord
-    (make_unibyte_string (proc.ki_comm, strlen (proc.ki_comm)),
-     Vlocale_coding_system, 0);
+  decoded_comm = (code_convert_string_norecord
+                 (build_unibyte_string (proc.ki_comm),
+                  Vlocale_coding_system, 0));
 
   attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
   {
@@ -3371,8 +3378,8 @@ system_process_attributes (Lisp_Object pid)
                 attrs);
   attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)),
                 attrs);
-  t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage.ru_utime),
-                     timeval_to_EMACS_TIME (proc.ki_rusage.ru_stime));
+  t = timespec_add (timeval_to_timespec (proc.ki_rusage.ru_utime),
+                   timeval_to_timespec (proc.ki_rusage.ru_stime));
   attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
 
   attrs = Fcons (Fcons (Qcutime,
@@ -3381,8 +3388,8 @@ system_process_attributes (Lisp_Object pid)
   attrs = Fcons (Fcons (Qcstime,
                        make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
                 attrs);
-  t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_utime),
-                     timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_stime));
+  t = timespec_add (timeval_to_timespec (proc.ki_rusage_ch.ru_utime),
+                   timeval_to_timespec (proc.ki_rusage_ch.ru_stime));
   attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
 
   attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)),
@@ -3394,8 +3401,8 @@ system_process_attributes (Lisp_Object pid)
   attrs = Fcons (Fcons (Qrss,   make_number (proc.ki_rssize * pagesize >> 10)),
                 attrs);
 
-  now = current_emacs_time ();
-  t = sub_emacs_time (now, timeval_to_EMACS_TIME (proc.ki_start));
+  now = current_timespec ();
+  t = timespec_sub (now, timeval_to_timespec (proc.ki_start));
   attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
 
   len = sizeof fscale;