diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2022-05-17 19:28:52 +0300 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2022-06-10 21:13:52 +0300 |
commit | b0cb9f85ca3626e0e68fd451c3090d253ceb4300 (patch) | |
tree | db9ff5315fbc1557040d70bda51787ea2fb5a086 /newlib/libc/stdio | |
parent | c4d4439c4208b75454edef0b42d5585de8ac9f47 (diff) |
Use global stdio streams for all configurations
The _REENT_GLOBAL_STDIO_STREAMS was introduced by commit
668a4c8722090fffd10869dbb15b879651c1370d in 2017. Since then it was enabled by
default for RTEMS. Recently, the option was enabled for Cygwin which
previously used an alternative implementation to use global stdio streams.
In Newlib, the stdio streams are defined to thread-specific pointers
_reent::_stdin, _reent::_stdout and _reent::_stderr. If the option is disabled
(the default for most systems), then these pointers are initialized to
thread-specific FILE objects which use file descriptors 0, 1, and 2,
respectively. There are at least three problems with this:
(1) The thread-specific FILE objects are closed by _reclaim_reent(). This
leads to problems with language run-time libraries that provide wrappers to
the C/POSIX stdio streams (for example C++ and Ada), since they use the
thread-specific FILE objects of the initialization thread. In case the
initialization thread is deleted, then they use freed memory.
(2) Since thread-specific FILE objects are used with a common output device via
file descriptors 0, 1 and 2, the locking at FILE object level cannot ensure
atomicity of the output, e.g. a call to printf().
(3) There are resource managment issues, see:
https://sourceware.org/pipermail/newlib/2022/019558.html
https://bugs.linaro.org/show_bug.cgi?id=5841
This patch enables the _REENT_GLOBAL_STDIO_STREAMS behaviour for all Newlib
configurations and removes the option. This removes a couple of #ifdef blocks.
Diffstat (limited to 'newlib/libc/stdio')
-rw-r--r-- | newlib/libc/stdio/fcloseall.c | 4 | ||||
-rw-r--r-- | newlib/libc/stdio/findfp.c | 53 | ||||
-rw-r--r-- | newlib/libc/stdio/local.h | 17 |
3 files changed, 1 insertions, 73 deletions
diff --git a/newlib/libc/stdio/fcloseall.c b/newlib/libc/stdio/fcloseall.c index 642dc7d94..e840af27c 100644 --- a/newlib/libc/stdio/fcloseall.c +++ b/newlib/libc/stdio/fcloseall.c @@ -59,12 +59,8 @@ Required OS subroutines: <<close>>, <<fstat>>, <<isatty>>, <<lseek>>, int _fcloseall_r (struct _reent *ptr) { -#ifdef _REENT_GLOBAL_STDIO_STREAMS /* There are no thread-specific FILE objects */ return 0; -#else - return _fwalk_sglue (ptr, _fclose_r, &ptr->__sglue); -#endif } #ifndef _REENT_ONLY diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c index 858c09ee3..ee991ed24 100644 --- a/newlib/libc/stdio/findfp.c +++ b/newlib/libc/stdio/findfp.c @@ -28,21 +28,9 @@ void (*__stdio_exit_handler) (void); -#if defined(_REENT_SMALL) && !defined(_REENT_GLOBAL_STDIO_STREAMS) -const struct __sFILE_fake __sf_fake_stdin = - {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL}; -const struct __sFILE_fake __sf_fake_stdout = - {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL}; -const struct __sFILE_fake __sf_fake_stderr = - {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL}; -#endif - -#ifdef _REENT_GLOBAL_STDIO_STREAMS __FILE __sf[3]; + struct _glue __sglue = {NULL, 3, &__sf[0]}; -#else -struct _glue __sglue = {NULL, 0, NULL}; -#endif #ifdef _STDIO_BSD_SEMANTICS /* BSD and Glibc systems only flush streams which have been written to @@ -161,11 +149,9 @@ global_stdio_init (void) { if (__stdio_exit_handler == NULL) { __stdio_exit_handler = stdio_exit_handler; -#ifdef _REENT_GLOBAL_STDIO_STREAMS stdin_init (&__sf[0]); stdout_init (&__sf[1]); stderr_init (&__sf[2]); -#endif } } @@ -232,16 +218,12 @@ found: static void cleanup_stdio (struct _reent *ptr) { -#ifdef _REENT_GLOBAL_STDIO_STREAMS if (ptr->_stdin != &__sf[0]) CLEANUP_FILE (ptr, ptr->_stdin); if (ptr->_stdout != &__sf[1]) CLEANUP_FILE (ptr, ptr->_stdout); if (ptr->_stderr != &__sf[2]) CLEANUP_FILE (ptr, ptr->_stderr); -#else - (void) _fwalk_sglue (ptr, CLEANUP_FILE, &ptr->__sglue); -#endif } /* @@ -262,22 +244,7 @@ __sinit (struct _reent *s) /* make sure we clean up on exit */ s->__cleanup = cleanup_stdio; /* conservative */ -#ifdef _REENT_SMALL -# ifndef _REENT_GLOBAL_STDIO_STREAMS - s->_stdin = __sfp(s); - s->_stdout = __sfp(s); - s->_stderr = __sfp(s); -# endif /* _REENT_GLOBAL_STDIO_STREAMS */ -#endif - global_stdio_init (); - -#ifndef _REENT_GLOBAL_STDIO_STREAMS - stdin_init (s->_stdin); - stdout_init (s->_stdout); - stderr_init (s->_stderr); -#endif /* _REENT_GLOBAL_STDIO_STREAMS */ - __sfp_lock_release (); } @@ -320,32 +287,14 @@ __fp_unlock (struct _reent * ptr __unused, FILE * fp) void __fp_lock_all (void) { -#ifndef _REENT_GLOBAL_STDIO_STREAMS - struct _reent *ptr; -#endif - __sfp_lock_acquire (); - -#ifndef _REENT_GLOBAL_STDIO_STREAMS - ptr = _REENT; - (void) _fwalk_sglue (ptr, __fp_lock, &ptr->__sglue); -#else (void) _fwalk_sglue (NULL, __fp_lock, &__sglue); -#endif } void __fp_unlock_all (void) { -#ifndef _REENT_GLOBAL_STDIO_STREAMS - struct _reent *ptr; - - ptr = _REENT; - (void) _fwalk_sglue (ptr, __fp_unlock, &ptr->__sglue); -#else (void) _fwalk_sglue (NULL, __fp_unlock, &__sglue); -#endif - __sfp_lock_release (); } #endif diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h index e245fdb4e..9b355e3ac 100644 --- a/newlib/libc/stdio/local.h +++ b/newlib/libc/stdio/local.h @@ -193,31 +193,14 @@ extern _READ_WRITE_RETURN_TYPE __swrite64 (struct _reent *, void *, /* Called by the main entry point fns to ensure stdio has been initialized. */ -#if defined(_REENT_SMALL) && !defined(_REENT_GLOBAL_STDIO_STREAMS) #define CHECK_INIT(ptr, fp) \ do \ { \ struct _reent *_check_init_ptr = (ptr); \ if ((_check_init_ptr) && !(_check_init_ptr)->__cleanup) \ __sinit (_check_init_ptr); \ - if ((fp) == (FILE *)&__sf_fake_stdin) \ - (fp) = _stdin_r(_check_init_ptr); \ - else if ((fp) == (FILE *)&__sf_fake_stdout) \ - (fp) = _stdout_r(_check_init_ptr); \ - else if ((fp) == (FILE *)&__sf_fake_stderr) \ - (fp) = _stderr_r(_check_init_ptr); \ } \ while (0) -#else /* !_REENT_SMALL || _REENT_GLOBAL_STDIO_STREAMS */ -#define CHECK_INIT(ptr, fp) \ - do \ - { \ - struct _reent *_check_init_ptr = (ptr); \ - if ((_check_init_ptr) && !(_check_init_ptr)->__cleanup) \ - __sinit (_check_init_ptr); \ - } \ - while (0) -#endif /* !_REENT_SMALL || _REENT_GLOBAL_STDIO_STREAMS */ /* Return true and set errno and stream error flag iff the given FILE cannot be written now. */ |