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