From f6ef15cf84c1288e972ef0e6165b97e34d6033b6 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 22 Jun 2017 11:21:20 -0700 Subject: [PATCH] Use unlocked stdio more systematically This can improve performance significantly on stdio-bottlenecked code. E.g., make-docfile is 3x faster on my Fedora 25 x86-64 desktop. * admin/merge-gnulib (GNULIB_MODULES): Add unlocked-io. * lib-src/ebrowse.c, lib-src/emacsclient.c, lib-src/etags.c: * lib-src/hexl.c, lib-src/make-docfile.c, lib-src/movemail.c: * lib-src/profile.c, lib-src/update-game-score.c: Include unlocked-io.h instead of stdio.h, since these programs are single-threaded. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/unlocked-io.h, m4/unlocked-io.m4: New files, copied from Gnulib. * src/charset.c, src/cm.c, src/emacs.c, src/image.c, src/keyboard.c: * src/lread.c, src/term.c: Include sysstdio.h, possibly instead of stdio.h, to define the unlocked functions if the system does not provide them. * src/charset.c, src/lread.c (getc_unlocked): Remove, since sysstdio.h now defines it if needed. * src/cm.c (cmputc, cmcheckmagic): * src/dispnew.c (update_frame, update_frame_with_menu) (update_frame_1, Fsend_string_to_terminal, Fding, bitch_at_user): * src/emacs.c (main, Fdump_emacs): * src/fileio.c (Fdo_auto_save, Fset_binary_mode): * src/image.c (slurp_file, png_read_from_file, png_load_body) (our_stdio_fill_input_buffer): * src/keyboard.c (record_char, kbd_buffer_get_event, handle_interrupt): * src/lread.c (readbyte_from_file): * src/minibuf.c (read_minibuf_noninteractive): * src/print.c (printchar_to_stream, strout) (Fredirect_debugging_output): * src/sysdep.c (reset_sys_modes, procfs_ttyname) (procfs_get_total_memory): * src/term.c (tty_ring_bell, tty_send_additional_strings) (tty_set_terminal_modes, tty_reset_terminal_modes) (tty_update_end, tty_clear_end_of_line, tty_write_glyphs) (tty_write_glyphs_with_face, tty_insert_glyphs) (tty_menu_activate): * src/xfaces.c (Fx_load_color_file): Use unlocked stdio when it should be safe. * src/sysstdio.h (clearerr_unlocked, feof_unlocked, ferror_unlocked) (fflush_unlocked, fgets_unlocked, fputc_unlocked, fputs_unlocked) (fread_unlocked, fwrite_unlocked, getc_unlocked, getchar_unlocked) (putc_unlocked, putchar_unloced): Provide substitutes if not declared. --- admin/merge-gnulib | 2 +- lib-src/ebrowse.c | 8 +-- lib-src/emacsclient.c | 3 +- lib-src/etags.c | 1 + lib-src/hexl.c | 2 +- lib-src/make-docfile.c | 10 +-- lib-src/movemail.c | 4 +- lib-src/profile.c | 2 +- lib-src/update-game-score.c | 3 +- lib/gnulib.mk.in | 11 ++- lib/unlocked-io.h | 136 ++++++++++++++++++++++++++++++++++++ m4/gnulib-comp.m4 | 4 ++ m4/unlocked-io.m4 | 41 +++++++++++ src/charset.c | 6 +- src/cm.c | 14 ++-- src/dispnew.c | 22 +++--- src/emacs.c | 8 +-- src/fileio.c | 16 ++--- src/image.c | 11 +-- src/keyboard.c | 19 ++--- src/lread.c | 11 +-- src/minibuf.c | 8 +-- src/print.c | 10 +-- src/sysdep.c | 15 ++-- src/sysstdio.h | 41 +++++++++++ src/term.c | 47 +++++++------ src/xfaces.c | 2 +- 27 files changed, 341 insertions(+), 116 deletions(-) create mode 100644 lib/unlocked-io.h create mode 100644 m4/unlocked-io.m4 diff --git a/admin/merge-gnulib b/admin/merge-gnulib index d4bbf17cb3d..85921ba1ba6 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -40,7 +40,7 @@ GNULIB_MODULES=' sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub - update-copyright utimens + update-copyright unlocked-io utimens vla warnings ' diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c index 51d181997b1..e77b7c94cca 100644 --- a/lib-src/ebrowse.c +++ b/lib-src/ebrowse.c @@ -20,21 +20,21 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include #include #include #include #include +#include +#include +#include + /* The SunOS compiler doesn't have SEEK_END. */ #ifndef SEEK_END #define SEEK_END 2 #endif -#include -#include - /* Files are read in chunks of this number of bytes. */ enum { READ_CHUNK_SIZE = 100 * 1024 }; diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 8828b7652de..f1d4e8976da 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -73,7 +73,6 @@ char *w32_getenv (const char *); #include #include -#include #include #include #include @@ -84,6 +83,8 @@ char *w32_getenv (const char *); #include #include +#include + #ifndef VERSION #define VERSION "unspecified" #endif diff --git a/lib-src/etags.c b/lib-src/etags.c index 6f280d8ab40..e5ff7bd10fc 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -123,6 +123,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4"; #include #include #include +#include #include #include diff --git a/lib-src/hexl.c b/lib-src/hexl.c index 319ce8bc890..d949af08902 100644 --- a/lib-src/hexl.c +++ b/lib-src/hexl.c @@ -22,11 +22,11 @@ along with this program. If not, see . */ #include #include -#include #include #include #include +#include static char *progname; diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 9470bd635f5..6b2cc110403 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -39,10 +39,14 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include #include #include +#include +#include +#include +#include + #ifdef WINDOWSNT /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this is really just insurance. */ @@ -50,10 +54,6 @@ along with GNU Emacs. If not, see . */ #include #endif /* WINDOWSNT */ -#include -#include -#include - #ifdef DOS_NT /* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this is really just insurance. diff --git a/lib-src/movemail.c b/lib-src/movemail.c index cd12c48ed36..e5ca0b16611 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c @@ -59,7 +59,6 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include #include #include #include @@ -69,6 +68,9 @@ along with GNU Emacs. If not, see . */ #include #include #include + +#include + #include "syswait.h" #ifdef MAIL_USE_POP #include "pop.h" diff --git a/lib-src/profile.c b/lib-src/profile.c index 253f00e2d80..f4ab45c1718 100644 --- a/lib-src/profile.c +++ b/lib-src/profile.c @@ -34,11 +34,11 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include #include #include +#include static struct timespec TV1; static int watch_not_started = 1; /* flag */ diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c index 5edc8e79569..942aeeb399d 100644 --- a/lib-src/update-game-score.c +++ b/lib-src/update-game-score.c @@ -39,7 +39,6 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include #include #include #include @@ -47,6 +46,8 @@ along with GNU Emacs. If not, see . */ #include #include +#include + #ifdef WINDOWSNT #include "ntlib.h" #endif diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 509089e6391..fd0f9e5c780 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 diffseq dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 diffseq dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings MOSTLYCLEANFILES += core *.stackdump @@ -2996,6 +2996,15 @@ EXTRA_DIST += unistd.in.h endif ## end gnulib module unistd +## begin gnulib module unlocked-io +ifeq (,$(OMIT_GNULIB_MODULE_unlocked-io)) + + +EXTRA_DIST += unlocked-io.h + +endif +## end gnulib module unlocked-io + ## begin gnulib module update-copyright ifeq (,$(OMIT_GNULIB_MODULE_update-copyright)) diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h new file mode 100644 index 00000000000..aaf60a0fb4e --- /dev/null +++ b/lib/unlocked-io.h @@ -0,0 +1,136 @@ +/* Prefer faster, non-thread-safe stdio functions if available. + + Copyright (C) 2001-2004, 2009-2017 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering. */ + +#ifndef UNLOCKED_IO_H +# define UNLOCKED_IO_H 1 + +/* These are wrappers for functions/macros from the GNU C library, and + from other C libraries supporting POSIX's optional thread-safe functions. + + The standard I/O functions are thread-safe. These *_unlocked ones are + more efficient but not thread-safe. That they're not thread-safe is + fine since all of the applications in this package are single threaded. + + Also, some code that is shared with the GNU C library may invoke + the *_unlocked functions directly. On hosts that lack those + functions, invoke the non-thread-safe versions instead. */ + +# include + +# if HAVE_DECL_CLEARERR_UNLOCKED +# undef clearerr +# define clearerr(x) clearerr_unlocked (x) +# else +# define clearerr_unlocked(x) clearerr (x) +# endif + +# if HAVE_DECL_FEOF_UNLOCKED +# undef feof +# define feof(x) feof_unlocked (x) +# else +# define feof_unlocked(x) feof (x) +# endif + +# if HAVE_DECL_FERROR_UNLOCKED +# undef ferror +# define ferror(x) ferror_unlocked (x) +# else +# define ferror_unlocked(x) ferror (x) +# endif + +# if HAVE_DECL_FFLUSH_UNLOCKED +# undef fflush +# define fflush(x) fflush_unlocked (x) +# else +# define fflush_unlocked(x) fflush (x) +# endif + +# if HAVE_DECL_FGETS_UNLOCKED +# undef fgets +# define fgets(x,y,z) fgets_unlocked (x,y,z) +# else +# define fgets_unlocked(x,y,z) fgets (x,y,z) +# endif + +# if HAVE_DECL_FPUTC_UNLOCKED +# undef fputc +# define fputc(x,y) fputc_unlocked (x,y) +# else +# define fputc_unlocked(x,y) fputc (x,y) +# endif + +# if HAVE_DECL_FPUTS_UNLOCKED +# undef fputs +# define fputs(x,y) fputs_unlocked (x,y) +# else +# define fputs_unlocked(x,y) fputs (x,y) +# endif + +# if HAVE_DECL_FREAD_UNLOCKED +# undef fread +# define fread(w,x,y,z) fread_unlocked (w,x,y,z) +# else +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +# endif + +# if HAVE_DECL_FWRITE_UNLOCKED +# undef fwrite +# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) +# else +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +# endif + +# if HAVE_DECL_GETC_UNLOCKED +# undef getc +# define getc(x) getc_unlocked (x) +# else +# define getc_unlocked(x) getc (x) +# endif + +# if HAVE_DECL_GETCHAR_UNLOCKED +# undef getchar +# define getchar() getchar_unlocked () +# else +# define getchar_unlocked() getchar () +# endif + +# if HAVE_DECL_PUTC_UNLOCKED +# undef putc +# define putc(x,y) putc_unlocked (x,y) +# else +# define putc_unlocked(x,y) putc (x,y) +# endif + +# if HAVE_DECL_PUTCHAR_UNLOCKED +# undef putchar +# define putchar(x) putchar_unlocked (x) +# else +# define putchar_unlocked(x) putchar (x) +# endif + +# undef flockfile +# define flockfile(x) ((void) 0) + +# undef ftrylockfile +# define ftrylockfile(x) 0 + +# undef funlockfile +# define funlockfile(x) ((void) 0) + +#endif /* UNLOCKED_IO_H */ diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 1ac58e871cc..107645df4fd 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -158,6 +158,7 @@ AC_DEFUN([gl_EARLY], # Code from module timespec-sub: # Code from module u64: # Code from module unistd: + # Code from module unlocked-io: # Code from module update-copyright: # Code from module utimens: # Code from module vararrays: @@ -399,6 +400,7 @@ AC_DEFUN([gl_INIT], gl_TIMER_TIME gl_TIMESPEC gl_UNISTD_H + gl_FUNC_GLIBC_UNLOCKED_IO gl_UTIMENS AC_C_VARARRAYS gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b=false @@ -940,6 +942,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/u64.h lib/unistd.c lib/unistd.in.h + lib/unlocked-io.h lib/utimens.c lib/utimens.h lib/verify.h @@ -1044,6 +1047,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/timespec.m4 m4/tm_gmtoff.m4 m4/unistd_h.m4 + m4/unlocked-io.m4 m4/utimens.m4 m4/utimes.m4 m4/vararrays.m4 diff --git a/m4/unlocked-io.m4 b/m4/unlocked-io.m4 new file mode 100644 index 00000000000..448ccac2f0e --- /dev/null +++ b/m4/unlocked-io.m4 @@ -0,0 +1,41 @@ +# unlocked-io.m4 serial 15 + +# Copyright (C) 1998-2006, 2009-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +dnl From Jim Meyering. +dnl +dnl See if the glibc *_unlocked I/O macros or functions are available. +dnl Use only those *_unlocked macros or functions that are declared +dnl (because some of them were declared in Solaris 2.5.1 but were removed +dnl in Solaris 2.6, whereas we want binaries built on Solaris 2.5.1 to run +dnl on Solaris 2.6). + +AC_DEFUN([gl_FUNC_GLIBC_UNLOCKED_IO], +[ + AC_DEFINE([USE_UNLOCKED_IO], [1], + [Define to 1 if you want getc etc. to use unlocked I/O if available. + Unlocked I/O can improve performance in unithreaded apps, + but it is not safe for multithreaded apps.]) + + dnl Persuade glibc and Solaris to declare + dnl fgets_unlocked(), fputs_unlocked() etc. + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_DECLS_ONCE([clearerr_unlocked]) + AC_CHECK_DECLS_ONCE([feof_unlocked]) + AC_CHECK_DECLS_ONCE([ferror_unlocked]) + AC_CHECK_DECLS_ONCE([fflush_unlocked]) + AC_CHECK_DECLS_ONCE([fgets_unlocked]) + AC_CHECK_DECLS_ONCE([fputc_unlocked]) + AC_CHECK_DECLS_ONCE([fputs_unlocked]) + AC_CHECK_DECLS_ONCE([fread_unlocked]) + AC_CHECK_DECLS_ONCE([fwrite_unlocked]) + AC_CHECK_DECLS_ONCE([getc_unlocked]) + AC_CHECK_DECLS_ONCE([getchar_unlocked]) + AC_CHECK_DECLS_ONCE([putc_unlocked]) + AC_CHECK_DECLS_ONCE([putchar_unlocked]) +]) diff --git a/src/charset.c b/src/charset.c index 9d15375dd79..d0840f7d2a9 100644 --- a/src/charset.c +++ b/src/charset.c @@ -29,7 +29,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include #include #include @@ -40,6 +39,7 @@ along with GNU Emacs. If not, see . */ #include "charset.h" #include "coding.h" #include "buffer.h" +#include "sysstdio.h" /*** GENERAL NOTES on CODED CHARACTER SETS (CHARSETS) *** @@ -198,10 +198,6 @@ static struct #define GET_TEMP_CHARSET_WORK_DECODER(CODE) \ (temp_charset_work->table.decoder[(CODE)]) - -#ifndef HAVE_GETC_UNLOCKED -#define getc_unlocked getc -#endif /* Set to 1 to warn that a charset map is loaded and thus a buffer diff --git a/src/cm.c b/src/cm.c index efa50b0f58d..9a90f37445c 100644 --- a/src/cm.c +++ b/src/cm.c @@ -19,10 +19,10 @@ along with GNU Emacs. If not, see . */ #include -#include #include "lisp.h" #include "cm.h" +#include "sysstdio.h" #include "termchar.h" #include "tparam.h" @@ -45,8 +45,8 @@ int cmputc (int c) { if (current_tty->termscript) - putc (c & 0177, current_tty->termscript); - putc (c & 0177, current_tty->output); + putc_unlocked (c & 0177, current_tty->termscript); + putc_unlocked (c & 0177, current_tty->output); return c; } @@ -117,11 +117,11 @@ cmcheckmagic (struct tty_display_info *tty) if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1) emacs_abort (); if (tty->termscript) - putc ('\r', tty->termscript); - putc ('\r', tty->output); + putc_unlocked ('\r', tty->termscript); + putc_unlocked ('\r', tty->output); if (tty->termscript) - putc ('\n', tty->termscript); - putc ('\n', tty->output); + putc_unlocked ('\n', tty->termscript); + putc_unlocked ('\n', tty->output); curX (tty) = 0; curY (tty)++; } diff --git a/src/dispnew.c b/src/dispnew.c index 27c69bde831..925e44d9804 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -3126,9 +3126,9 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p) if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) { if (FRAME_TTY (f)->termscript) - fflush (FRAME_TTY (f)->termscript); + fflush_unlocked (FRAME_TTY (f)->termscript); if (FRAME_TERMCAP_P (f)) - fflush (FRAME_TTY (f)->output); + fflush_unlocked (FRAME_TTY (f)->output); } /* Check window matrices for lost pointers. */ @@ -3181,8 +3181,8 @@ update_frame_with_menu (struct frame *f, int row, int col) update_end (f); if (FRAME_TTY (f)->termscript) - fflush (FRAME_TTY (f)->termscript); - fflush (FRAME_TTY (f)->output); + fflush_unlocked (FRAME_TTY (f)->termscript); + fflush_unlocked (FRAME_TTY (f)->output); /* Check window matrices for lost pointers. */ #if GLYPH_DEBUG #if 0 @@ -4531,7 +4531,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, ptrdiff_t outq = __fpending (display_output); if (outq > 900 || (outq > 20 && ((i - 1) % preempt_count == 0))) - fflush (display_output); + fflush_unlocked (display_output); } } @@ -5615,13 +5615,13 @@ when TERMINAL is nil. */) if (tty->termscript) { - fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); - fflush (tty->termscript); + fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->termscript); + fflush_unlocked (tty->termscript); } out = tty->output; } - fwrite (SDATA (string), 1, SBYTES (string), out); - fflush (out); + fwrite_unlocked (SDATA (string), 1, SBYTES (string), out); + fflush_unlocked (out); unblock_input (); return Qnil; } @@ -5636,7 +5636,7 @@ terminate any keyboard macro currently executing. */) if (!NILP (arg)) { if (noninteractive) - putchar (07); + putchar_unlocked (07); else ring_bell (XFRAME (selected_frame)); } @@ -5650,7 +5650,7 @@ void bitch_at_user (void) { if (noninteractive) - putchar (07); + putchar_unlocked (07); else if (!INTERACTIVE) /* Stop executing a keyboard macro. */ { const char *msg diff --git a/src/emacs.c b/src/emacs.c index da8df1bf1c7..0fec7167588 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -23,7 +23,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include #include @@ -33,6 +32,7 @@ along with GNU Emacs. If not, see . */ #define MAIN_PROGRAM #include "lisp.h" +#include "sysstdio.h" #ifdef WINDOWSNT #include @@ -885,7 +885,7 @@ main (int argc, char **argv) } #endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */ - clearerr (stdin); + clearerr_unlocked (stdin); emacs_backtrace (-1); @@ -983,7 +983,7 @@ main (int argc, char **argv) int i; printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); for (i = 0; i < ARRAYELTS (usage_message); i++) - fputs (usage_message[i], stdout); + fputs_unlocked (usage_message[i], stdout); exit (0); } @@ -2197,7 +2197,7 @@ You must run Emacs in batch mode in order to dump it. */) } #endif - fflush (stdout); + fflush_unlocked (stdout); /* Tell malloc where start of impure now is. */ /* Also arrange for warnings when nearly out of space. */ #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC diff --git a/src/fileio.c b/src/fileio.c index cb070029a9b..a57d50b24e0 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5643,14 +5643,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) { block_input (); if (!NILP (BVAR (b, filename))) - { - fwrite (SDATA (BVAR (b, filename)), 1, - SBYTES (BVAR (b, filename)), stream); - } - putc ('\n', stream); - fwrite (SDATA (BVAR (b, auto_save_file_name)), 1, - SBYTES (BVAR (b, auto_save_file_name)), stream); - putc ('\n', stream); + fwrite_unlocked (SDATA (BVAR (b, filename)), 1, + SBYTES (BVAR (b, filename)), stream); + putc_unlocked ('\n', stream); + fwrite_unlocked (SDATA (BVAR (b, auto_save_file_name)), 1, + SBYTES (BVAR (b, auto_save_file_name)), stream); + putc_unlocked ('\n', stream); unblock_input (); } @@ -5841,7 +5839,7 @@ effect except for flushing STREAM's data. */) binmode = NILP (mode) ? O_TEXT : O_BINARY; if (fp != stdin) - fflush (fp); + fflush_unlocked (fp); return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; } diff --git a/src/image.c b/src/image.c index aedec7954ee..07c4769e9e3 100644 --- a/src/image.c +++ b/src/image.c @@ -20,7 +20,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include /* Include this before including to work around bugs with @@ -41,6 +40,7 @@ along with GNU Emacs. If not, see . */ #include "buffer.h" #include "dispextern.h" #include "blockinput.h" +#include "sysstdio.h" #include "systime.h" #include #include "coding.h" @@ -2361,7 +2361,7 @@ slurp_file (int fd, ptrdiff_t *size) This can happen if the file grows as we read it. */ ptrdiff_t buflen = st.st_size; buf = xmalloc (buflen + 1); - if (fread (buf, 1, buflen + 1, fp) == buflen) + if (fread_unlocked (buf, 1, buflen + 1, fp) == buflen) *size = buflen; else { @@ -5890,7 +5890,7 @@ png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length) { FILE *fp = png_get_io_ptr (png_ptr); - if (fread (data, 1, length, fp) < length) + if (fread_unlocked (data, 1, length, fp) < length) png_error (png_ptr, "Read error"); } @@ -5959,7 +5959,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) } /* Check PNG signature. */ - if (fread (sig, 1, sizeof sig, fp) != sizeof sig + if (fread_unlocked (sig, 1, sizeof sig, fp) != sizeof sig || png_sig_cmp (sig, 0, sizeof sig)) { fclose (fp); @@ -6598,7 +6598,8 @@ our_stdio_fill_input_buffer (j_decompress_ptr cinfo) { ptrdiff_t bytes; - bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file); + bytes = fread_unlocked (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, + src->file); if (bytes > 0) src->mgr.bytes_in_buffer = bytes; else diff --git a/src/keyboard.c b/src/keyboard.c index 55486c6d9ab..3442b18409a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -39,6 +39,7 @@ along with GNU Emacs. If not, see . */ #include "intervals.h" #include "keymap.h" #include "blockinput.h" +#include "sysstdio.h" #include "systime.h" #include "atimer.h" #include "process.h" @@ -3290,7 +3291,7 @@ record_char (Lisp_Object c) if (INTEGERP (c)) { if (XUINT (c) < 0x100) - putc (XUINT (c), dribble); + putc_unlocked (XUINT (c), dribble); else fprintf (dribble, " 0x%"pI"x", XUINT (c)); } @@ -3303,15 +3304,15 @@ record_char (Lisp_Object c) if (SYMBOLP (dribblee)) { - putc ('<', dribble); - fwrite (SDATA (SYMBOL_NAME (dribblee)), sizeof (char), - SBYTES (SYMBOL_NAME (dribblee)), - dribble); - putc ('>', dribble); + putc_unlocked ('<', dribble); + fwrite_unlocked (SDATA (SYMBOL_NAME (dribblee)), sizeof (char), + SBYTES (SYMBOL_NAME (dribblee)), + dribble); + putc_unlocked ('>', dribble); } } - fflush (dribble); + fflush_unlocked (dribble); unblock_input (); } } @@ -3769,7 +3770,7 @@ kbd_buffer_get_event (KBOARD **kbp, detaching from the terminal. */ || (IS_DAEMON && DAEMON_RUNNING)) { - int c = getchar (); + int c = getchar_unlocked (); XSETINT (obj, c); *kbp = current_kboard; return obj; @@ -10377,7 +10378,7 @@ handle_interrupt (bool in_signal_handler) sigemptyset (&blocked); sigaddset (&blocked, SIGINT); pthread_sigmask (SIG_BLOCK, &blocked, 0); - fflush (stdout); + fflush_unlocked (stdout); } reset_all_sys_modes (); diff --git a/src/lread.c b/src/lread.c index 8716b86e9bf..182f96223a5 100644 --- a/src/lread.c +++ b/src/lread.c @@ -72,10 +72,6 @@ along with GNU Emacs. If not, see . */ #define file_tell ftell #endif -#ifndef HAVE_GETC_UNLOCKED -#define getc_unlocked getc -#endif - /* The objects or placeholders read with the #n=object form. A hash table maps a number to either a placeholder (while the @@ -474,16 +470,15 @@ readbyte_from_file (int c, Lisp_Object readcharfun) } block_input (); - c = getc_unlocked (instream); /* Interrupted reads have been observed while reading over the network. */ - while (c == EOF && ferror (instream) && errno == EINTR) + while ((c = getc_unlocked (instream)) == EOF && errno == EINTR + && ferror_unlocked (instream)) { unblock_input (); maybe_quit (); block_input (); - clearerr (instream); - c = getc_unlocked (instream); + clearerr_unlocked (instream); } unblock_input (); diff --git a/src/minibuf.c b/src/minibuf.c index 1bbe276776e..835992fa79d 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -20,7 +20,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include @@ -31,6 +30,7 @@ along with GNU Emacs. If not, see . */ #include "frame.h" #include "window.h" #include "keymap.h" +#include "sysstdio.h" #include "systty.h" /* List of buffers for use as minibuffers. @@ -209,15 +209,15 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, suppress_echo_on_tty (STDIN_FILENO); } - fwrite (SDATA (prompt), 1, SBYTES (prompt), stdout); - fflush (stdout); + fwrite_unlocked (SDATA (prompt), 1, SBYTES (prompt), stdout); + fflush_unlocked (stdout); val = Qnil; size = 100; len = 0; line = xmalloc (size); - while ((c = getchar ()) != '\n' && c != '\r') + while ((c = getchar_unlocked ()) != '\n' && c != '\r') { if (c == EOF) { diff --git a/src/print.c b/src/print.c index aaec5b04956..6bf8af9ef93 100644 --- a/src/print.c +++ b/src/print.c @@ -228,7 +228,7 @@ printchar_to_stream (unsigned int ch, FILE *stream) { if (ASCII_CHAR_P (ch)) { - putc (ch, stream); + putc_unlocked (ch, stream); #ifdef WINDOWSNT /* Send the output to a debugger (nothing happens if there isn't one). */ @@ -246,7 +246,7 @@ printchar_to_stream (unsigned int ch, FILE *stream) if (encode_p) encoded_ch = code_convert_string_norecord (encoded_ch, coding_system, true); - fwrite (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream); + fwrite_unlocked (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream); #ifdef WINDOWSNT if (print_output_debug_flag && stream == stderr) OutputDebugString (SSDATA (encoded_ch)); @@ -298,7 +298,7 @@ printchar (unsigned int ch, Lisp_Object fun) if (DISP_TABLE_P (Vstandard_display_table)) printchar_to_stream (ch, stdout); else - fwrite (str, 1, len, stdout); + fwrite_unlocked (str, 1, len, stdout); noninteractive_need_newline = 1; } else @@ -350,7 +350,7 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte, } } else - fwrite (ptr, 1, size_byte, stdout); + fwrite_unlocked (ptr, 1, size_byte, stdout); noninteractive_need_newline = 1; } @@ -801,7 +801,7 @@ append to existing target file. */) report_file_error ("Cannot open debugging output stream", file); } - fflush (stderr); + fflush_unlocked (stderr); if (dup2 (fd, STDERR_FILENO) < 0) report_file_error ("dup2", file); if (fd != stderr_dup) diff --git a/src/sysdep.c b/src/sysdep.c index 70f4a9dd7ea..b52236769e0 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1408,7 +1408,7 @@ reset_sys_modes (struct tty_display_info *tty_out) { if (noninteractive) { - fflush (stdout); + fflush_unlocked (stdout); return; } if (!tty_out->term_initted) @@ -1428,17 +1428,14 @@ reset_sys_modes (struct tty_display_info *tty_out) } else { /* have to do it the hard way */ - int i; tty_turn_off_insert (tty_out); - for (i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++) - { - fputc (' ', tty_out->output); - } + for (int i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++) + fputc_unlocked (' ', tty_out->output); } cmgoto (tty_out, FrameRows (tty_out) - 1, 0); - fflush (tty_out->output); + fflush_unlocked (tty_out->output); if (tty_out->terminal->reset_terminal_modes_hook) tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal); @@ -3079,7 +3076,7 @@ procfs_ttyname (int rdev) char minor[25]; /* 2 32-bit numbers + dash */ char *endp; - for (; !feof (fdev) && !ferror (fdev); name[0] = 0) + for (; !feof_unlocked (fdev) && !ferror_unlocked (fdev); name[0] = 0) { if (fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) >= 3 && major == MAJOR (rdev)) @@ -3129,7 +3126,7 @@ procfs_get_total_memory (void) break; case 0: - while ((c = getc (fmem)) != EOF && c != '\n') + while ((c = getc_unlocked (fmem)) != EOF && c != '\n') continue; done = c == EOF; break; diff --git a/src/sysstdio.h b/src/sysstdio.h index 45ee33f5580..7fbcefcdad9 100644 --- a/src/sysstdio.h +++ b/src/sysstdio.h @@ -33,4 +33,45 @@ extern FILE *emacs_fopen (char const *, char const *); # define FOPEN_TEXT "" #endif +/* These are compatible with unlocked-io.h, if both files are included. */ +#if !HAVE_DECL_CLEARERR_UNLOCKED +# define clearerr_unlocked(x) clearerr (x) +#endif +#if !HAVE_DECL_FEOF_UNLOCKED +# define feof_unlocked(x) feof (x) +#endif +#if !HAVE_DECL_FERROR_UNLOCKED +# define ferror_unlocked(x) ferror (x) +#endif +#if !HAVE_DECL_FFLUSH_UNLOCKED +# define fflush_unlocked(x) fflush (x) +#endif +#if !HAVE_DECL_FGETS_UNLOCKED +# define fgets_unlocked(x,y,z) fgets (x,y,z) +#endif +#if !HAVE_DECL_FPUTC_UNLOCKED +# define fputc_unlocked(x,y) fputc (x,y) +#endif +#if !HAVE_DECL_FPUTS_UNLOCKED +# define fputs_unlocked(x,y) fputs (x,y) +#endif +#if !HAVE_DECL_FREAD_UNLOCKED +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +#endif +#if !HAVE_DECL_FWRITE_UNLOCKED +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +#endif +#if !HAVE_DECL_GETC_UNLOCKED +# define getc_unlocked(x) getc (x) +#endif +#if !HAVE_DECL_GETCHAR_UNLOCKED +# define getchar_unlocked() getchar () +#endif +#if !HAVE_DECL_PUTC_UNLOCKED +# define putc_unlocked(x,y) putc (x,y) +#endif +#if !HAVE_DECL_PUTCHAR_UNLOCKED +# define putchar_unlocked(x) putchar (x) +#endif + #endif /* EMACS_SYSSTDIO_H */ diff --git a/src/term.c b/src/term.c index 8770aff8a92..3d7f4ada0b9 100644 --- a/src/term.c +++ b/src/term.c @@ -22,7 +22,6 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include #include #include #include @@ -45,6 +44,7 @@ along with GNU Emacs. If not, see . */ #include "keymap.h" #include "blockinput.h" #include "syssignal.h" +#include "sysstdio.h" #ifdef MSDOS #include "msdos.h" static int been_here = -1; @@ -146,7 +146,7 @@ tty_ring_bell (struct frame *f) OUTPUT (tty, (tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell)); - fflush (tty->output); + fflush_unlocked (tty->output); } } @@ -167,9 +167,10 @@ tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym) Lisp_Object string = XCAR (extra_codes); if (STRINGP (string)) { - fwrite (SDATA (string), 1, SBYTES (string), tty->output); + fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->output); if (tty->termscript) - fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); + fwrite_unlocked (SDATA (string), 1, SBYTES (string), + tty->termscript); } } } @@ -197,7 +198,7 @@ tty_set_terminal_modes (struct terminal *terminal) OUTPUT_IF (tty, tty->TS_keypad_mode); losecursor (tty); tty_send_additional_strings (terminal, Qtty_mode_set_strings); - fflush (tty->output); + fflush_unlocked (tty->output); } } @@ -220,7 +221,7 @@ tty_reset_terminal_modes (struct terminal *terminal) /* Output raw CR so kernel can track the cursor hpos. */ current_tty = tty; cmputc ('\r'); - fflush (tty->output); + fflush_unlocked (tty->output); } } @@ -235,7 +236,7 @@ tty_update_end (struct frame *f) tty_show_cursor (tty); tty_turn_off_insert (tty); tty_background_highlight (tty); - fflush (tty->output); + fflush_unlocked (tty->output); } /* The implementation of set_terminal_window for termcap frames. */ @@ -497,8 +498,8 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos) for (i = curX (tty); i < first_unused_hpos; i++) { if (tty->termscript) - fputc (' ', tty->termscript); - fputc (' ', tty->output); + fputc_unlocked (' ', tty->termscript); + fputc_unlocked (' ', tty->output); } cmplus (tty, first_unused_hpos - curX (tty)); } @@ -771,11 +772,11 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len) if (coding->produced > 0) { block_input (); - fwrite (conversion_buffer, 1, coding->produced, tty->output); - if (ferror (tty->output)) - clearerr (tty->output); + fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output); + clearerr_unlocked (tty->output); if (tty->termscript) - fwrite (conversion_buffer, 1, coding->produced, tty->termscript); + fwrite_unlocked (conversion_buffer, 1, coding->produced, + tty->termscript); unblock_input (); } string += n; @@ -832,11 +833,11 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str if (coding->produced > 0) { block_input (); - fwrite (conversion_buffer, 1, coding->produced, tty->output); - if (ferror (tty->output)) - clearerr (tty->output); + fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output); + clearerr_unlocked (tty->output); if (tty->termscript) - fwrite (conversion_buffer, 1, coding->produced, tty->termscript); + fwrite_unlocked (conversion_buffer, 1, coding->produced, + tty->termscript); unblock_input (); } @@ -918,11 +919,11 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len) if (coding->produced > 0) { block_input (); - fwrite (conversion_buffer, 1, coding->produced, tty->output); - if (ferror (tty->output)) - clearerr (tty->output); + fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output); + clearerr_unlocked (tty->output); if (tty->termscript) - fwrite (conversion_buffer, 1, coding->produced, tty->termscript); + fwrite_unlocked (conversion_buffer, 1, coding->produced, + tty->termscript); unblock_input (); } @@ -3327,7 +3328,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, which calls tty_show_cursor. Re-hide it, so it doesn't show through the menus. */ tty_hide_cursor (tty); - fflush (tty->output); + fflush_unlocked (tty->output); } sf->mouse_moved = 0; @@ -3335,7 +3336,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, while (statecount--) free_saved_screen (state[statecount].screen_behind); tty_show_cursor (tty); /* Turn cursor back on. */ - fflush (tty->output); + fflush_unlocked (tty->output); /* Clean up any mouse events that are waiting inside Emacs event queue. These events are likely to be generated before the menu was even diff --git a/src/xfaces.c b/src/xfaces.c index 4714b7b3cb8..86bb9b0b496 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -6232,7 +6232,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */) int red, green, blue; int num; - while (fgets (buf, sizeof (buf), fp) != NULL) { + while (fgets_unlocked (buf, sizeof (buf), fp) != NULL) { if (sscanf (buf, "%d %d %d %n", &red, &green, &blue, &num) == 3) { #ifdef HAVE_NTGUI -- 2.39.2