aboutsummaryrefslogtreecommitdiffstats
path: root/src/sysdep.c
diff options
context:
space:
mode:
authorPaul Eggert2012-06-22 14:17:42 -0700
committerPaul Eggert2012-06-22 14:17:42 -0700
commitd35af63cd671563fd188c3b0a1ef30067027c7aa (patch)
treec9e01847ccf788e23794684da9331c3e0defd0d3 /src/sysdep.c
parentf143bfe38b43ad0a9d817f05c25e418982dca06f (diff)
downloademacs-d35af63cd671563fd188c3b0a1ef30067027c7aa.tar.gz
emacs-d35af63cd671563fd188c3b0a1ef30067027c7aa.zip
Support higher-resolution time stamps.
Fixes: debbugs:9000
Diffstat (limited to 'src/sysdep.c')
-rw-r--r--src/sysdep.c227
1 files changed, 101 insertions, 126 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 3356582de0c..8d1c3d0ca3c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32#include <allocator.h> 32#include <allocator.h>
33#include <careadlinkat.h> 33#include <careadlinkat.h>
34#include <ignore-value.h> 34#include <ignore-value.h>
35#include <utimens.h>
35 36
36#include "lisp.h" 37#include "lisp.h"
37#include "sysselect.h" 38#include "sysselect.h"
@@ -109,20 +110,6 @@ extern char *getwd (char *);
109 110
110#include "syssignal.h" 111#include "syssignal.h"
111#include "systime.h" 112#include "systime.h"
112#ifdef HAVE_UTIME_H
113#include <utime.h>
114#endif
115
116#ifndef HAVE_UTIMES
117#ifndef HAVE_STRUCT_UTIMBUF
118/* We want to use utime rather than utimes, but we couldn't find the
119 structure declaration. We'll use the traditional one. */
120struct utimbuf {
121 long actime;
122 long modtime;
123};
124#endif
125#endif
126 113
127static int emacs_get_tty (int, struct emacs_tty *); 114static int emacs_get_tty (int, struct emacs_tty *);
128static int emacs_set_tty (int, struct emacs_tty *, int); 115static int emacs_set_tty (int, struct emacs_tty *, int);
@@ -2067,30 +2054,6 @@ perror (void)
2067#endif /* HPUX and not HAVE_PERROR */ 2054#endif /* HPUX and not HAVE_PERROR */
2068 2055
2069/* 2056/*
2070 * Gettimeofday. Simulate as much as possible. Only accurate
2071 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2072 * Only needed when subprocesses are defined.
2073 */
2074
2075#ifndef HAVE_GETTIMEOFDAY
2076#ifdef HAVE_TIMEVAL
2077
2078int
2079gettimeofday (struct timeval *tp, struct timezone *tzp)
2080{
2081 extern long time (long);
2082
2083 tp->tv_sec = time ((long *)0);
2084 tp->tv_usec = 0;
2085 if (tzp != 0)
2086 tzp->tz_minuteswest = -1;
2087 return 0;
2088}
2089
2090#endif
2091#endif /* !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
2092
2093/*
2094 * This function will go away as soon as all the stubs fixed. (fnf) 2057 * This function will go away as soon as all the stubs fixed. (fnf)
2095 */ 2058 */
2096 2059
@@ -2126,20 +2089,43 @@ closedir (DIR *dirp /* stream from opendir */)
2126#endif /* HAVE_DIRENT_H */ 2089#endif /* HAVE_DIRENT_H */
2127 2090
2128 2091
2092/* Return a struct timeval that is roughly equivalent to T.
2093 Use the least timeval not less than T.
2094 Return an extremal value if the result would overflow. */
2095struct timeval
2096make_timeval (EMACS_TIME t)
2097{
2098 struct timeval tv;
2099 tv.tv_sec = t.tv_sec;
2100 tv.tv_usec = t.tv_nsec / 1000;
2101
2102 if (t.tv_nsec % 1000 != 0)
2103 {
2104 if (tv.tv_usec < 999999)
2105 tv.tv_usec++;
2106 else if (tv.tv_sec < TYPE_MAXIMUM (time_t))
2107 {
2108 tv.tv_sec++;
2109 tv.tv_usec = 0;
2110 }
2111 }
2112
2113 return tv;
2114}
2115
2116/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2117 ATIME and MTIME, respectively.
2118 FD must be either negative -- in which case it is ignored --
2119 or a file descriptor that is open on FILE.
2120 If FD is nonnegative, then FILE can be NULL. */
2129int 2121int
2130set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime) 2122set_file_times (int fd, const char *filename,
2131{ 2123 EMACS_TIME atime, EMACS_TIME mtime)
2132#ifdef HAVE_UTIMES 2124{
2133 struct timeval tv[2]; 2125 struct timespec timespec[2];
2134 tv[0] = atime; 2126 timespec[0] = atime;
2135 tv[1] = mtime; 2127 timespec[1] = mtime;
2136 return utimes (filename, tv); 2128 return fdutimens (fd, filename, timespec);
2137#else /* not HAVE_UTIMES */
2138 struct utimbuf utb;
2139 utb.actime = EMACS_SECS (atime);
2140 utb.modtime = EMACS_SECS (mtime);
2141 return utime (filename, &utb);
2142#endif /* not HAVE_UTIMES */
2143} 2129}
2144 2130
2145/* mkdir and rmdir functions, for systems which don't have them. */ 2131/* mkdir and rmdir functions, for systems which don't have them. */
@@ -2595,60 +2581,82 @@ list_system_processes (void)
2595#endif /* !defined (WINDOWSNT) */ 2581#endif /* !defined (WINDOWSNT) */
2596 2582
2597#ifdef GNU_LINUX 2583#ifdef GNU_LINUX
2598static void 2584static EMACS_TIME
2599time_from_jiffies (unsigned long long tval, long hz, 2585time_from_jiffies (unsigned long long tval, long hz)
2600 time_t *sec, unsigned *usec) 2586{
2601{ 2587 unsigned long long s = tval / hz;
2602 unsigned long long ullsec; 2588 unsigned long long frac = tval % hz;
2603 2589 int ns;
2604 *sec = tval / hz; 2590 EMACS_TIME t;
2605 ullsec = *sec; 2591
2606 tval -= ullsec * hz; 2592 if (TYPE_MAXIMUM (time_t) < s)
2607 /* Careful: if HZ > 1 million, then integer division by it yields zero. */ 2593 time_overflow ();
2608 if (hz <= 1000000) 2594 if (LONG_MAX - 1 <= ULLONG_MAX / EMACS_TIME_RESOLUTION
2609 *usec = tval * 1000000 / hz; 2595 || frac <= ULLONG_MAX / EMACS_TIME_RESOLUTION)
2596 ns = frac * EMACS_TIME_RESOLUTION / hz;
2610 else 2597 else
2611 *usec = tval / (hz / 1000000); 2598 {
2599 /* This is reachable only in the unlikely case that HZ * HZ
2600 exceeds ULLONG_MAX. It calculates an approximation that is
2601 guaranteed to be in range. */
2602 long hz_per_ns = (hz / EMACS_TIME_RESOLUTION
2603 + (hz % EMACS_TIME_RESOLUTION != 0));
2604 ns = frac / hz_per_ns;
2605 }
2606
2607 EMACS_SET_SECS_NSECS (t, s, ns);
2608 return t;
2612} 2609}
2613 2610
2614static Lisp_Object 2611static Lisp_Object
2615ltime_from_jiffies (unsigned long long tval, long hz) 2612ltime_from_jiffies (unsigned long long tval, long hz)
2616{ 2613{
2617 time_t sec; 2614 EMACS_TIME t = time_from_jiffies (tval, hz);
2618 unsigned usec; 2615 return make_lisp_time (t);
2619
2620 time_from_jiffies (tval, hz, &sec, &usec);
2621
2622 return list3 (make_number ((sec >> 16) & 0xffff),
2623 make_number (sec & 0xffff),
2624 make_number (usec));
2625} 2616}
2626 2617
2627static void 2618static EMACS_TIME
2628get_up_time (time_t *sec, unsigned *usec) 2619get_up_time (void)
2629{ 2620{
2630 FILE *fup; 2621 FILE *fup;
2622 EMACS_TIME up;
2631 2623
2632 *sec = *usec = 0; 2624 EMACS_SET_SECS_NSECS (up, 0, 0);
2633 2625
2634 BLOCK_INPUT; 2626 BLOCK_INPUT;
2635 fup = fopen ("/proc/uptime", "r"); 2627 fup = fopen ("/proc/uptime", "r");
2636 2628
2637 if (fup) 2629 if (fup)
2638 { 2630 {
2639 double uptime, idletime; 2631 unsigned long long upsec, upfrac, idlesec, idlefrac;
2632 int upfrac_start, upfrac_end, idlefrac_start, idlefrac_end;
2640 2633
2641 /* The numbers in /proc/uptime use C-locale decimal point, but 2634 if (fscanf (fup, "%llu.%n%llu%n %llu.%n%llu%n",
2642 we already set ourselves to the C locale (see `fixup_locale' 2635 &upsec, &upfrac_start, &upfrac, &upfrac_end,
2643 in emacs.c). */ 2636 &idlesec, &idlefrac_start, &idlefrac, &idlefrac_end)
2644 if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime)) 2637 == 4)
2645 { 2638 {
2646 *sec = uptime; 2639 if (TYPE_MAXIMUM (time_t) < upsec)
2647 *usec = (uptime - *sec) * 1000000; 2640 {
2641 upsec = TYPE_MAXIMUM (time_t);
2642 upfrac = EMACS_TIME_RESOLUTION - 1;
2643 }
2644 else
2645 {
2646 int upfraclen = upfrac_end - upfrac_start;
2647 for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++)
2648 upfrac *= 10;
2649 for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--)
2650 upfrac /= 10;
2651 upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
2652 }
2653 EMACS_SET_SECS_NSECS (up, upsec, upfrac);
2648 } 2654 }
2649 fclose (fup); 2655 fclose (fup);
2650 } 2656 }
2651 UNBLOCK_INPUT; 2657 UNBLOCK_INPUT;
2658
2659 return up;
2652} 2660}
2653 2661
2654#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff) 2662#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
@@ -2748,9 +2756,7 @@ system_process_attributes (Lisp_Object pid)
2748 unsigned long long u_time, s_time, cutime, cstime, start; 2756 unsigned long long u_time, s_time, cutime, cstime, start;
2749 long priority, niceness, rss; 2757 long priority, niceness, rss;
2750 unsigned long minflt, majflt, cminflt, cmajflt, vsize; 2758 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
2751 time_t sec; 2759 EMACS_TIME tnow, tstart, tboot, telapsed, us_time;
2752 unsigned usec;
2753 EMACS_TIME tnow, tstart, tboot, telapsed;
2754 double pcpu, pmem; 2760 double pcpu, pmem;
2755 Lisp_Object attrs = Qnil; 2761 Lisp_Object attrs = Qnil;
2756 Lisp_Object cmd_str, decoded_cmd, tem; 2762 Lisp_Object cmd_str, decoded_cmd, tem;
@@ -2873,35 +2879,18 @@ system_process_attributes (Lisp_Object pid)
2873 attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs); 2879 attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs);
2874 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs); 2880 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
2875 EMACS_GET_TIME (tnow); 2881 EMACS_GET_TIME (tnow);
2876 get_up_time (&sec, &usec); 2882 telapsed = get_up_time ();
2877 EMACS_SET_SECS (telapsed, sec);
2878 EMACS_SET_USECS (telapsed, usec);
2879 EMACS_SUB_TIME (tboot, tnow, telapsed); 2883 EMACS_SUB_TIME (tboot, tnow, telapsed);
2880 time_from_jiffies (start, clocks_per_sec, &sec, &usec); 2884 tstart = time_from_jiffies (start, clocks_per_sec);
2881 EMACS_SET_SECS (tstart, sec);
2882 EMACS_SET_USECS (tstart, usec);
2883 EMACS_ADD_TIME (tstart, tboot, tstart); 2885 EMACS_ADD_TIME (tstart, tboot, tstart);
2884 attrs = Fcons (Fcons (Qstart, 2886 attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs);
2885 list3 (make_number
2886 ((EMACS_SECS (tstart) >> 16) & 0xffff),
2887 make_number
2888 (EMACS_SECS (tstart) & 0xffff),
2889 make_number
2890 (EMACS_USECS (tstart)))),
2891 attrs);
2892 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs); 2887 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
2893 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs); 2888 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
2894 EMACS_SUB_TIME (telapsed, tnow, tstart); 2889 EMACS_SUB_TIME (telapsed, tnow, tstart);
2895 attrs = Fcons (Fcons (Qetime, 2890 attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
2896 list3 (make_number 2891 us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
2897 ((EMACS_SECS (telapsed) >> 16) & 0xffff), 2892 pcpu = (EMACS_TIME_TO_DOUBLE (us_time)
2898 make_number 2893 / EMACS_TIME_TO_DOUBLE (telapsed));
2899 (EMACS_SECS (telapsed) & 0xffff),
2900 make_number
2901 (EMACS_USECS (telapsed)))),
2902 attrs);
2903 time_from_jiffies (u_time + s_time, clocks_per_sec, &sec, &usec);
2904 pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
2905 if (pcpu > 1.0) 2894 if (pcpu > 1.0)
2906 pcpu = 1.0; 2895 pcpu = 1.0;
2907 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs); 2896 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
@@ -3082,27 +3071,13 @@ system_process_attributes (Lisp_Object pid)
3082 Qcstime 3071 Qcstime
3083 Are they available? */ 3072 Are they available? */
3084 3073
3085 attrs = Fcons (Fcons (Qtime, 3074 attrs = Fcons (Fcons (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
3086 list3 (make_number (pinfo.pr_time.tv_sec >> 16), 3075 attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), attrs);
3087 make_number (pinfo.pr_time.tv_sec & 0xffff),
3088 make_number (pinfo.pr_time.tv_nsec))),
3089 attrs);
3090
3091 attrs = Fcons (Fcons (Qctime,
3092 list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
3093 make_number (pinfo.pr_ctime.tv_sec & 0xffff),
3094 make_number (pinfo.pr_ctime.tv_nsec))),
3095 attrs);
3096
3097 attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs); 3076 attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
3098 attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs); 3077 attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
3099 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs); 3078 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
3100 3079
3101 attrs = Fcons (Fcons (Qstart, 3080 attrs = Fcons (Fcons (Qstart, make_lisp_time (pinfo.pr_start)), attrs);
3102 list3 (make_number (pinfo.pr_start.tv_sec >> 16),
3103 make_number (pinfo.pr_start.tv_sec & 0xffff),
3104 make_number (pinfo.pr_start.tv_nsec))),
3105 attrs);
3106 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs); 3081 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
3107 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs); 3082 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
3108 3083