RE: [PATCH 14/14] Add --enable-newlib-reent-thread-local option

Torbjorn SVENSSON via Newlib <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <AM6PR10MB2197C24E0A59090946EBEB7B81B39@AM6PR10MB2197.EURPRD10.PROD.OUTLOOK.COM>
Hello Sebastian,

Just out of curiosity, how will this impact RTOSes like FreeRTOS?
Currently, FreeRTOS updates the impure_ptr to point to an instance of struct _reent that belongs to that particular task when the scheduler is switching task. 

See https://www.freertos.org/a00110.html#configUSE_NEWLIB_REENTRANT and https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/tasks.c#L2047 for details.

Kind regards,
Torbjörn

> -----Original Message-----
> From: Newlib <newlib-
> [email protected]> On Behalf Of
> Sebastian Huber
> Sent: den 21 juni 2022 14:50
> To: [email protected]
> Subject: [PATCH 14/14] Add --enable-newlib-reent-thread-local option
> 
> From: Matt Joyce <[email protected]>
> 
> By default, Newlib uses a huge object of type struct _reent to store
> thread-specific data.  This object is returned by __getreent() if the
> __DYNAMIC_REENT__ Newlib configuration option is defined.
> 
> The reentrancy structure contains for example errno and the standard input,
> output, and error file streams.  This means that if an application only uses
> errno it has a dependency on the file stream support even if it does not use
> it.  This is an issue for lower end targets and applications which need to
> qualify the software according to safety standards (for example ECSS-E-ST-
> 40C,
> ECSS-Q-ST-80C, IEC 61508, ISO 26262, DO-178, DO-330, DO-333).
> 
> If the new _REENT_THREAD_LOCAL configuration option is enabled, then
> struct
> _reent is replaced by dedicated thread-local objects for each struct _reent
> member.  The thread-local objects are defined in translation units which use
> the corresponding object.
> ---
>  newlib/README                    |  8 +++
>  newlib/configure                 | 21 ++++++++
>  newlib/configure.ac              | 15 ++++++
>  newlib/libc/errno/errno.c        |  6 +++
>  newlib/libc/include/sys/config.h |  6 +++
>  newlib/libc/include/sys/errno.h  |  6 +++
>  newlib/libc/include/sys/reent.h  | 92 ++++++++++++++++++++++++++++++++
>  newlib/libc/locale/locale.c      |  4 ++
>  newlib/libc/reent/impure.c       |  4 ++
>  newlib/libc/reent/reent.c        |  2 +
>  newlib/libc/signal/signal.c      |  4 ++
>  newlib/libc/stdio/findfp.c       |  7 +++
>  newlib/libc/stdio/tmpnam.c       |  5 ++
>  newlib/libc/stdlib/dtoa.c        |  5 ++
>  newlib/libc/stdlib/ecvtbuf.c     |  5 ++
>  newlib/libc/stdlib/l64a.c        |  4 ++
>  newlib/libc/stdlib/lcong48.c     |  8 +++
>  newlib/libc/stdlib/mblen.c       |  4 ++
>  newlib/libc/stdlib/mbrlen.c      |  4 ++
>  newlib/libc/stdlib/mbrtowc.c     |  4 ++
>  newlib/libc/stdlib/mbsnrtowcs.c  |  4 ++
>  newlib/libc/stdlib/mbtowc.c      |  4 ++
>  newlib/libc/stdlib/mprec.c       |  5 ++
>  newlib/libc/stdlib/rand.c        |  4 ++
>  newlib/libc/stdlib/wcrtomb.c     |  4 ++
>  newlib/libc/stdlib/wcsnrtombs.c  |  4 ++
>  newlib/libc/stdlib/wctomb.c      |  4 ++
>  newlib/libc/string/strsignal.c   |  4 ++
>  newlib/libc/string/strtok.c      |  4 ++
>  newlib/libc/time/asctime.c       |  4 ++
>  newlib/libc/time/gmtime.c        |  4 ++
>  newlib/libm/math/w_lgamma.c      |  4 ++
>  newlib/newlib.hin                |  4 ++
>  33 files changed, 267 insertions(+)
> 
> diff --git a/newlib/README b/newlib/README
> index dd4686eeb..1b2c16cd4 100644
> --- a/newlib/README
> +++ b/newlib/README
> @@ -304,6 +304,14 @@ One feature can be enabled by specifying `--enable-
> FEATURE=yes' or
>       layout.
>       Disabled by default.
> 
> +`--enable-newlib-reent-thread-local'
> +     Enable thread-local storage objects as a replacement for struct _reent
> +     members.  If enabled, then struct _reent is not defined and dedicated
> +     thread-local storage objects are provided for each member of the default
> +     struct _reent.  For statically linked executables only the objects
> +     required by the application are linked in.
> +     Disabled by default.
> +
>  `--disable-newlib-fvwrite-in-streamio'
>       NEWLIB implements the vector buffer mechanism to support stream IO
>       buffering required by C standard.  This feature is possibly
> diff --git a/newlib/configure b/newlib/configure
> index 82c256694..e493eb293 100755
> --- a/newlib/configure
> +++ b/newlib/configure
> @@ -973,6 +973,7 @@ enable_newlib_atexit_dynamic_alloc
>  enable_newlib_global_atexit
>  enable_newlib_reent_small
>  enable_newlib_reent_binary_compat
> +enable_newlib_reent_thread_local
>  enable_newlib_global_stdio_streams
>  enable_newlib_fvwrite_in_streamio
>  enable_newlib_fseek_optimization
> @@ -1641,6 +1642,7 @@ Optional Features:
>    --enable-newlib-global-atexit	enable atexit data structure as
> global
>    --enable-newlib-reent-small   enable small reentrant struct support
>    --enable-newlib-reent-binary-compat   enable backward binary
> compatibility for struct _reent
> +  --enable-newlib-reent-thread-local   enable thread-local storage objects as
> a replacment for struct _reent members
>    --enable-newlib-global-stdio-streams   enable global stdio streams
>    --disable-newlib-fvwrite-in-streamio    disable iov in streamio
>    --disable-newlib-fseek-optimization    disable fseek optimization
> @@ -2404,6 +2406,19 @@ else
>    newlib_reent_binary_compat=no
>  fi
> 
> +# Check whether --enable-newlib-reent-thread-local was given.
> +if test "${enable_newlib_reent_thread_local+set}" = set; then :
> +  enableval=$enable_newlib_reent_thread_local; if test
> "${newlib_reent_thread_local+set}" != set; then
> +  case "${enableval}" in
> +    yes) newlib_reent_thread_local=yes ;;
> +    no)  newlib_reent_thread_local=no  ;;
> +    *)   as_fn_error $? "bad value ${enableval} for newlib-enable-reent-
> thread-local option" "$LINENO" 5 ;;
> +  esac
> + fi
> +else
> +  newlib_reent_thread_local=no
> +fi
> +
>  # Check whether --enable-newlib-global-stdio-streams was given.
>  if test "${enable_newlib_global_stdio_streams+set}" = set; then :
>    enableval=$enable_newlib_global_stdio_streams; case "${enableval}" in
> @@ -6437,6 +6452,12 @@ $as_echo "#define
> _WANT_REENT_BACKWARD_BINARY_COMPAT 1" >>confdefs.h
> 
>  fi
> 
> +if test "${newlib_reent_thread_local}" = "yes"; then
> +
> +$as_echo "#define _WANT_REENT_THREAD_LOCAL 1" >>confdefs.h
> +
> +fi
> +
>  _mb_len_max=1
>  if test "${newlib_mb}" = "yes"; then
> 
> diff --git a/newlib/configure.ac b/newlib/configure.ac
> index 1951aab0c..bed444db0 100644
> --- a/newlib/configure.ac
> +++ b/newlib/configure.ac
> @@ -173,6 +173,17 @@ AC_ARG_ENABLE(newlib-reent-binary-compat,
>    esac
>   fi], [newlib_reent_binary_compat=no])dnl
> 
> +dnl Support --enable-newlib-reent-thread-local
> +AC_ARG_ENABLE(newlib-reent-thread-local,
> +[  --enable-newlib-reent-thread-local   enable thread-local storage objects as
> a replacment for struct _reent members],
> +[if test "${newlib_reent_thread_local+set}" != set; then
> +  case "${enableval}" in
> +    yes) newlib_reent_thread_local=yes ;;
> +    no)  newlib_reent_thread_local=no  ;;
> +    *)   AC_MSG_ERROR(bad value ${enableval} for newlib-enable-reent-
> thread-local option) ;;
> +  esac
> + fi], [newlib_reent_thread_local=no])dnl
> +
>  dnl Support --enable-newlib-global-stdio-streams
>  dnl This is no longer optional.  It is enabled in all Newlib configurations.
>  AC_ARG_ENABLE(newlib-global-stdio-streams,
> @@ -435,6 +446,10 @@ if test "${newlib_reent_binary_compat}" = "yes";
> then
>    AC_DEFINE(_WANT_REENT_BACKWARD_BINARY_COMPAT, 1, [Define to
> enable backward binary compatibility for struct _reent.])
>  fi
> 
> +if test "${newlib_reent_thread_local}" = "yes"; then
> +  AC_DEFINE(_WANT_REENT_THREAD_LOCAL, 1, [Define to enable thread-
> local storage objects as a replacment for struct _reent members.])
> +fi
> +
>  _mb_len_max=1
>  if test "${newlib_mb}" = "yes"; then
>    AC_DEFINE(_MB_CAPABLE, 1, [Multibyte supported.])
> diff --git a/newlib/libc/errno/errno.c b/newlib/libc/errno/errno.c
> index 70402924b..384b07f2c 100644
> --- a/newlib/libc/errno/errno.c
> +++ b/newlib/libc/errno/errno.c
> @@ -5,6 +5,10 @@
>  #include <errno.h>
>  #include <reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local int _tls_errno;
> +#else /* !_REENT_THREAD_LOCAL */
> +
>  #ifndef _REENT_ONLY
> 
>  int *
> @@ -14,3 +18,5 @@ __errno ()
>  }
> 
>  #endif
> +
> +#endif /* _REENT_THREAD_LOCAL */
> diff --git a/newlib/libc/include/sys/config.h
> b/newlib/libc/include/sys/config.h
> index 4bce10de3..5dcc77a80 100644
> --- a/newlib/libc/include/sys/config.h
> +++ b/newlib/libc/include/sys/config.h
> @@ -297,6 +297,12 @@
>  #endif
>  #endif
> 
> +#ifdef _WANT_REENT_THREAD_LOCAL
> +#ifndef _REENT_THREAD_LOCAL
> +#define _REENT_THREAD_LOCAL
> +#endif
> +#endif
> +
>  /* If _MB_EXTENDED_CHARSETS_ALL is set, we want all of the extended
>     charsets.  The extended charsets add a few functions and a couple
>     of tables of a few K each. */
> diff --git a/newlib/libc/include/sys/errno.h b/newlib/libc/include/sys/errno.h
> index 995f30e05..f1509712e 100644
> --- a/newlib/libc/include/sys/errno.h
> +++ b/newlib/libc/include/sys/errno.h
> @@ -10,11 +10,17 @@ extern "C" {
> 
>  #include <sys/reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +#define errno (_tls_errno)
> +#else /* _REENT_THREAD_LOCAL */
> +
>  #ifndef _REENT_ONLY
>  #define errno (*__errno())
>  extern int *__errno (void);
>  #endif
> 
> +#endif /* _REENT_THREAD_LOCAL */
> +
>  /* Please don't use these variables directly.
>     Use strerror instead. */
>  extern __IMPORT const char * const _sys_errlist[];
> diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h
> index 90f848180..71342bebc 100644
> --- a/newlib/libc/include/sys/reent.h
> +++ b/newlib/libc/include/sys/reent.h
> @@ -301,6 +301,8 @@ struct _rand48 {
>  #define _REENT_ASCTIME_SIZE 26
>  #define _REENT_SIGNAL_SIZE 24
> 
> +#ifndef _REENT_THREAD_LOCAL
> +
>  #ifdef _REENT_BACKWARD_BINARY_COMPAT
>  #define _REENT_INIT_RESERVED_0 0,
>  #define _REENT_INIT_RESERVED_1 0,
> @@ -767,6 +769,96 @@ extern struct _reent _impure_data
> __ATTRIBUTE_IMPURE_DATA__;
> 
>  #define _GLOBAL_REENT (&_impure_data)
> 
> +#else /* _REENT_THREAD_LOCAL */
> +
> +#define _REENT NULL
> +#define _GLOBAL_REENT NULL
> +
> +/*
> + * Since _REENT is defined as NULL, this macro ensures that calls to
> + * CHECK_INIT() do not automatically fail.
> + */
> +#define _REENT_IS_NULL(_ptr) 0
> +
> +#define _REENT_CHECK_RAND48(ptr)	/* nothing */
> +#define _REENT_CHECK_MP(ptr)		/* nothing */
> +#define _REENT_CHECK_TM(ptr)		/* nothing */
> +#define _REENT_CHECK_ASCTIME_BUF(ptr)	/* nothing */
> +#define _REENT_CHECK_EMERGENCY(ptr)	/* nothing */
> +#define _REENT_CHECK_MISC(ptr)		/* nothing */
> +#define _REENT_CHECK_SIGNAL_BUF(ptr)	/* nothing */
> +
> +extern _Thread_local char _tls_asctime_buf[_REENT_ASCTIME_SIZE];
> +#define _REENT_ASCTIME_BUF(_ptr) (_tls_asctime_buf)
> +extern _Thread_local char *_tls_cvtbuf;
> +#define _REENT_CVTBUF(_ptr) (_tls_cvtbuf)
> +extern _Thread_local int _tls_cvtlen;
> +#define _REENT_CVTLEN(_ptr) (_tls_cvtlen)
> +extern _Thread_local void (*_tls_cleanup)(struct _reent *);
> +#define _REENT_CLEANUP(_ptr) (_tls_cleanup)
> +extern _Thread_local char _tls_emergency;
> +#define _REENT_EMERGENCY(_ptr) (_tls_emergency)
> +extern _Thread_local int _tls_errno;
> +#define _REENT_ERRNO(_ptr) (_tls_errno)
> +extern _Thread_local int _tls_getdate_err;
> +#define _REENT_GETDATE_ERR_P(_ptr) (&_tls_getdate_err)
> +extern _Thread_local int _tls_inc;
> +#define _REENT_INC(_ptr) (_tls_inc)
> +extern _Thread_local char _tls_l64a_buf[8];
> +#define _REENT_L64A_BUF(_ptr) (_tls_l64a_buf)
> +extern _Thread_local struct __locale_t *_tls_locale;
> +#define _REENT_LOCALE(_ptr) (_tls_locale)
> +extern _Thread_local _mbstate_t _tls_mblen_state;
> +#define _REENT_MBLEN_STATE(_ptr) (_tls_mblen_state)
> +extern _Thread_local _mbstate_t _tls_mbrlen_state;
> +#define _REENT_MBRLEN_STATE(_ptr) (_tls_mbrlen_state)
> +extern _Thread_local _mbstate_t _tls_mbrtowc_state;
> +#define _REENT_MBRTOWC_STATE(_ptr) (_tls_mbrtowc_state)
> +extern _Thread_local _mbstate_t _tls_mbsrtowcs_state;
> +#define _REENT_MBSRTOWCS_STATE(_ptr) (_tls_mbsrtowcs_state)
> +extern _Thread_local _mbstate_t _tls_mbtowc_state;
> +#define _REENT_MBTOWC_STATE(_ptr) (_tls_mbtowc_state)
> +extern _Thread_local struct _Bigint **_tls_mp_freelist;
> +#define _REENT_MP_FREELIST(_ptr) (_tls_mp_freelist)
> +extern _Thread_local struct _Bigint *_tls_mp_p5s;
> +#define _REENT_MP_P5S(_ptr) (_tls_mp_p5s)
> +extern _Thread_local struct _Bigint *_tls_mp_result;
> +#define _REENT_MP_RESULT(_ptr) (_tls_mp_result)
> +extern _Thread_local int _tls_mp_result_k;
> +#define _REENT_MP_RESULT_K(_ptr) (_tls_mp_result_k)
> +extern _Thread_local unsigned short _tls_rand48_add;
> +#define _REENT_RAND48_ADD(_ptr) (_tls_rand48_add)
> +extern _Thread_local unsigned short _tls_rand48_mult[3];
> +#define _REENT_RAND48_MULT(_ptr) (_tls_rand48_mult)
> +extern _Thread_local unsigned short _tls_rand48_seed[3];
> +#define _REENT_RAND48_SEED(_ptr) (_tls_rand48_seed)
> +extern _Thread_local unsigned long long _tls_rand_next;
> +#define _REENT_RAND_NEXT(_ptr) (_tls_rand_next)
> +extern _Thread_local void (**_tls_sig_func)(int);
> +#define _REENT_SIG_FUNC(_ptr) (_tls_sig_func)
> +extern _Thread_local char _tls_signal_buf[_REENT_SIGNAL_SIZE];
> +#define _REENT_SIGNAL_BUF(_ptr) (_tls_signal_buf)
> +extern _Thread_local int _tls_gamma_signgam;
> +#define _REENT_SIGNGAM(_ptr) (_tls_gamma_signgam)
> +extern _Thread_local __FILE *_tls_stdin;
> +#define _REENT_STDIN(_ptr) (_tls_stdin)
> +extern _Thread_local __FILE *_tls_stdout;
> +#define _REENT_STDOUT(_ptr) (_tls_stdout)
> +extern _Thread_local __FILE *_tls_stderr;
> +#define _REENT_STDERR(_ptr) (_tls_stderr)
> +extern _Thread_local char *_tls_strtok_last;
> +#define _REENT_STRTOK_LAST(_ptr) (_tls_strtok_last)
> +extern _Thread_local struct __tm _tls_localtime_buf;
> +#define _REENT_TM(_ptr) (&_tls_localtime_buf)
> +extern _Thread_local _mbstate_t _tls_wctomb_state;
> +#define _REENT_WCTOMB_STATE(_ptr) (_tls_wctomb_state)
> +extern _Thread_local _mbstate_t _tls_wcrtomb_state;
> +#define _REENT_WCRTOMB_STATE(_ptr) (_tls_wcrtomb_state)
> +extern _Thread_local _mbstate_t _tls_wcsrtombs_state;
> +#define _REENT_WCSRTOMBS_STATE(_ptr) (_tls_wcsrtombs_state)
> +
> +#endif /* !_REENT_THREAD_LOCAL */
> +
>  /* This value is used in stdlib/misc.c.  reent/reent.c has to know it
>     as well to make sure the freelist is correctly free'd.  Therefore
>     we define it here, rather than in stdlib/misc.c, as before. */
> diff --git a/newlib/libc/locale/locale.c b/newlib/libc/locale/locale.c
> index 968642745..e523d2366 100644
> --- a/newlib/libc/locale/locale.c
> +++ b/newlib/libc/locale/locale.c
> @@ -166,6 +166,10 @@ No supporting OS subroutines are required.
>  #include "../ctype/ctype_.h"
>  #include "../stdlib/local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local struct __locale_t *_tls_locale;
> +#endif
> +
>  #ifdef __CYGWIN__ /* Has to be kept available as exported symbol for
>  		     backward compatibility.  Set it in setlocale,
> but
>  		     otherwise ignore it.  Applications compiled
> after
> diff --git a/newlib/libc/reent/impure.c b/newlib/libc/reent/impure.c
> index 9290c9cd5..a87b91feb 100644
> --- a/newlib/libc/reent/impure.c
> +++ b/newlib/libc/reent/impure.c
> @@ -1,5 +1,7 @@
>  #include <reent.h>
> 
> +#ifndef _REENT_THREAD_LOCAL
> +
>  /* Redeclare these symbols locally as weak so that the file containing
>     their definitions (along with a lot of other stuff) isn't sucked in
>     unless they are actually used by other compilation units.  This is
> @@ -14,3 +16,5 @@ struct _reent __ATTRIBUTE_IMPURE_DATA__
> _impure_data = _REENT_INIT (_impure_data
>  extern struct _reent reent_data __attribute__ ((alias("_impure_data")));
>  #endif
>  struct _reent *__ATTRIBUTE_IMPURE_PTR__ _impure_ptr = &_impure_data;
> +
> +#endif /* _REENT_THREAD_LOCAL */
> diff --git a/newlib/libc/reent/reent.c b/newlib/libc/reent/reent.c
> index 4e9485c7a..db80ca06e 100644
> --- a/newlib/libc/reent/reent.c
> +++ b/newlib/libc/reent/reent.c
> @@ -30,7 +30,9 @@ int errno;
>  void
>  _reclaim_reent (struct _reent *ptr)
>  {
> +#ifndef _REENT_THREAD_LOCAL
>    if (ptr != _impure_ptr)
> +#endif
>      {
>        /* used by mprec routines. */
>  #ifdef _REENT_SMALL
> diff --git a/newlib/libc/signal/signal.c b/newlib/libc/signal/signal.c
> index 3f14b4712..77d78f04a 100644
> --- a/newlib/libc/signal/signal.c
> +++ b/newlib/libc/signal/signal.c
> @@ -88,6 +88,10 @@ int _dummy_simulated_signal;
>  #include <reent.h>
>  #include <_syslist.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local void (**_tls_sig_func)(int);
> +#endif
> +
>  int
>  _init_signal_r (struct _reent *ptr)
>  {
> diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c
> index fbdb7f2f2..c43028209 100644
> --- a/newlib/libc/stdio/findfp.c
> +++ b/newlib/libc/stdio/findfp.c
> @@ -32,6 +32,13 @@ __FILE __sf[3];
> 
>  struct _glue __sglue = {NULL, 3, &__sf[0]};
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local __FILE *_tls_stdin = &__sf[0];
> +_Thread_local __FILE *_tls_stdout = &__sf[1];
> +_Thread_local __FILE *_tls_stderr = &__sf[2];
> +_Thread_local void (*_tls_cleanup)(struct _reent *);
> +#endif
> +
>  #ifdef _STDIO_BSD_SEMANTICS
>    /* BSD and Glibc systems only flush streams which have been written to
>       at exit time.  Calling flush rather than close for speed, as on
> diff --git a/newlib/libc/stdio/tmpnam.c b/newlib/libc/stdio/tmpnam.c
> index 2767b4b20..51dfd1cea 100644
> --- a/newlib/libc/stdio/tmpnam.c
> +++ b/newlib/libc/stdio/tmpnam.c
> @@ -82,6 +82,11 @@ The global pointer <<environ>> is also required.
>  #include <reent.h>
>  #include <errno.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local int _tls_inc;
> +_Thread_local char _tls_emergency;
> +#endif
> +
>  /* Try to open the file specified, if it can't be opened then try
>     another one.  Return nonzero if successful, otherwise zero.  */
> 
> diff --git a/newlib/libc/stdlib/dtoa.c b/newlib/libc/stdlib/dtoa.c
> index e47a8bc77..198fa663a 100644
> --- a/newlib/libc/stdlib/dtoa.c
> +++ b/newlib/libc/stdlib/dtoa.c
> @@ -32,6 +32,11 @@
>  #include <string.h>
>  #include "mprec.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local struct _Bigint *_tls_mp_result;
> +_Thread_local int _tls_mp_result_k;
> +#endif
> +
>  static int
>  quorem (_Bigint * b, _Bigint * S)
>  {
> diff --git a/newlib/libc/stdlib/ecvtbuf.c b/newlib/libc/stdlib/ecvtbuf.c
> index 05f315108..514896682 100644
> --- a/newlib/libc/stdlib/ecvtbuf.c
> +++ b/newlib/libc/stdlib/ecvtbuf.c
> @@ -57,6 +57,11 @@ Supporting OS subroutines required: <<close>>,
> <<fstat>>, <<isatty>>,
>  #include "mprec.h"
>  #include "local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local char *_tls_cvtbuf;
> +_Thread_local int _tls_cvtlen;
> +#endif
> +
>  static void
>  print_f (struct _reent *ptr,
>  	char *buf,
> diff --git a/newlib/libc/stdlib/l64a.c b/newlib/libc/stdlib/l64a.c
> index 45282e32d..6f12b6151 100644
> --- a/newlib/libc/stdlib/l64a.c
> +++ b/newlib/libc/stdlib/l64a.c
> @@ -24,6 +24,10 @@
>  #include <stdlib.h>
>  #include <reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local char _tls_l64a_buf[8];
> +#endif
> +
>  static const char R64_ARRAY[] =
> "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
> yz";
> 
>  char *
> diff --git a/newlib/libc/stdlib/lcong48.c b/newlib/libc/stdlib/lcong48.c
> index 78e9e5746..d1109f0ac 100644
> --- a/newlib/libc/stdlib/lcong48.c
> +++ b/newlib/libc/stdlib/lcong48.c
> @@ -13,6 +13,14 @@
> 
>  #include "rand48.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local unsigned short _tls_rand48_seed[3] = {_RAND48_SEED_0,
> _RAND48_SEED_1,
> +    _RAND48_SEED_2};
> +_Thread_local unsigned short _tls_rand48_mult[3] = {_RAND48_MULT_0,
> _RAND48_MULT_1,
> +    _RAND48_MULT_2};
> +_Thread_local unsigned short _tls_rand48_add = _RAND48_ADD;
> +#endif
> +
>  void
>  _lcong48_r (struct _reent *r,
>         unsigned short p[7])
> diff --git a/newlib/libc/stdlib/mblen.c b/newlib/libc/stdlib/mblen.c
> index 3753d3673..24df61519 100644
> --- a/newlib/libc/stdlib/mblen.c
> +++ b/newlib/libc/stdlib/mblen.c
> @@ -42,6 +42,10 @@ effects vary with the locale.
>  #include <wchar.h>
>  #include "local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_mblen_state;
> +#endif
> +
>  int
>  mblen (const char *s,
>          size_t n)
> diff --git a/newlib/libc/stdlib/mbrlen.c b/newlib/libc/stdlib/mbrlen.c
> index 57a733fed..39e175e43 100644
> --- a/newlib/libc/stdlib/mbrlen.c
> +++ b/newlib/libc/stdlib/mbrlen.c
> @@ -5,6 +5,10 @@
>  #include <stdio.h>
>  #include <errno.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_mbrlen_state;
> +#endif
> +
>  size_t
>  mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps)
>  {
> diff --git a/newlib/libc/stdlib/mbrtowc.c b/newlib/libc/stdlib/mbrtowc.c
> index 521b7a5f4..e641b8cd6 100644
> --- a/newlib/libc/stdlib/mbrtowc.c
> +++ b/newlib/libc/stdlib/mbrtowc.c
> @@ -7,6 +7,10 @@
>  #include <string.h>
>  #include "local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_mbrtowc_state;
> +#endif
> +
>  size_t
>  _mbrtowc_r (struct _reent *ptr,
>  	wchar_t *pwc,
> diff --git a/newlib/libc/stdlib/mbsnrtowcs.c
> b/newlib/libc/stdlib/mbsnrtowcs.c
> index 8f94b1da5..2effc501c 100644
> --- a/newlib/libc/stdlib/mbsnrtowcs.c
> +++ b/newlib/libc/stdlib/mbsnrtowcs.c
> @@ -70,6 +70,10 @@ PORTABILITY
>  #include <stdio.h>
>  #include <errno.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_mbsrtowcs_state;
> +#endif
> +
>  size_t
>  _mbsnrtowcs_r (struct _reent *r,
>  	wchar_t *dst,
> diff --git a/newlib/libc/stdlib/mbtowc.c b/newlib/libc/stdlib/mbtowc.c
> index 2dc413f2d..fbd8df61d 100644
> --- a/newlib/libc/stdlib/mbtowc.c
> +++ b/newlib/libc/stdlib/mbtowc.c
> @@ -49,6 +49,10 @@ effects vary with the locale.
>  #include <wchar.h>
>  #include "local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_mbtowc_state;
> +#endif
> +
>  int
>  mbtowc (wchar_t *__restrict pwc,
>          const char *__restrict s,
> diff --git a/newlib/libc/stdlib/mprec.c b/newlib/libc/stdlib/mprec.c
> index 930c984ca..1f534b068 100644
> --- a/newlib/libc/stdlib/mprec.c
> +++ b/newlib/libc/stdlib/mprec.c
> @@ -86,6 +86,11 @@
>  #include <reent.h>
>  #include "mprec.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local struct _Bigint *_tls_mp_p5s;
> +_Thread_local struct _Bigint **_tls_mp_freelist;
> +#endif
> +
>  /* This is defined in sys/reent.h as (sizeof (size_t) << 3) now, as in NetBSD.
>     The old value of 15 was wrong and made newlib vulnerable against buffer
>     overrun attacks (CVE-2009-0689), same as other implementations of gdtoa
> diff --git a/newlib/libc/stdlib/rand.c b/newlib/libc/stdlib/rand.c
> index 209cb32ff..ba9cc80f2 100644
> --- a/newlib/libc/stdlib/rand.c
> +++ b/newlib/libc/stdlib/rand.c
> @@ -58,6 +58,10 @@ on two different systems.
>  #include <stdlib.h>
>  #include <reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local unsigned long long _tls_rand_next = 1;
> +#endif
> +
>  void
>  srand (unsigned int seed)
>  {
> diff --git a/newlib/libc/stdlib/wcrtomb.c b/newlib/libc/stdlib/wcrtomb.c
> index 6d670e23a..1b84720ac 100644
> --- a/newlib/libc/stdlib/wcrtomb.c
> +++ b/newlib/libc/stdlib/wcrtomb.c
> @@ -6,6 +6,10 @@
>  #include <errno.h>
>  #include "local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_wcrtomb_state;
> +#endif
> +
>  size_t
>  _wcrtomb_r (struct _reent *ptr,
>  	char *s,
> diff --git a/newlib/libc/stdlib/wcsnrtombs.c
> b/newlib/libc/stdlib/wcsnrtombs.c
> index dfd974f24..abef7ac36 100644
> --- a/newlib/libc/stdlib/wcsnrtombs.c
> +++ b/newlib/libc/stdlib/wcsnrtombs.c
> @@ -72,6 +72,10 @@ PORTABILITY
>  #include "local.h"
>  #include "../locale/setlocale.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_wcsrtombs_state;
> +#endif
> +
>  size_t
>  _wcsnrtombs_l (struct _reent *r, char *dst, const wchar_t **src, size_t nwc,
>  	       size_t len, mbstate_t *ps, struct __locale_t *loc)
> diff --git a/newlib/libc/stdlib/wctomb.c b/newlib/libc/stdlib/wctomb.c
> index e908d22c2..f56dccf25 100644
> --- a/newlib/libc/stdlib/wctomb.c
> +++ b/newlib/libc/stdlib/wctomb.c
> @@ -45,6 +45,10 @@ effects vary with the locale.
>  #include <errno.h>
>  #include "local.h"
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local _mbstate_t _tls_wctomb_state;
> +#endif
> +
>  int
>  wctomb (char *s,
>          wchar_t wchar)
> diff --git a/newlib/libc/string/strsignal.c b/newlib/libc/string/strsignal.c
> index 544857b14..89d39fe3c 100644
> --- a/newlib/libc/string/strsignal.c
> +++ b/newlib/libc/string/strsignal.c
> @@ -52,6 +52,10 @@ QUICKREF
>  #include <stdlib.h>
>  #include <reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local char _tls_signal_buf[_REENT_SIGNAL_SIZE];
> +#endif
> +
>  char *
>  strsignal (int signal)
>  {
> diff --git a/newlib/libc/string/strtok.c b/newlib/libc/string/strtok.c
> index 801f51aca..2a11c9196 100644
> --- a/newlib/libc/string/strtok.c
> +++ b/newlib/libc/string/strtok.c
> @@ -74,6 +74,10 @@ QUICKREF
>  #include <_ansi.h>
>  #include <reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local char *_tls_strtok_last;
> +#endif
> +
>  #ifndef _REENT_ONLY
> 
>  extern char *__strtok_r (char *, const char *, char **, int);
> diff --git a/newlib/libc/time/asctime.c b/newlib/libc/time/asctime.c
> index 9aa26c3dc..a81506181 100644
> --- a/newlib/libc/time/asctime.c
> +++ b/newlib/libc/time/asctime.c
> @@ -45,6 +45,10 @@ ANSI C requires <<asctime>>.
>  #include <_ansi.h>
>  #include <reent.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local char _tls_asctime_buf[_REENT_ASCTIME_SIZE];
> +#endif
> +
>  #ifndef _REENT_ONLY
> 
>  char *
> diff --git a/newlib/libc/time/gmtime.c b/newlib/libc/time/gmtime.c
> index 08e011129..a78d55433 100644
> --- a/newlib/libc/time/gmtime.c
> +++ b/newlib/libc/time/gmtime.c
> @@ -47,6 +47,10 @@ ANSI C requires <<gmtime>>.
> 
>  #define _GMT_OFFSET 0
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local struct __tm _tls_localtime_buf;
> +#endif
> +
>  #ifndef _REENT_ONLY
> 
>  struct tm *
> diff --git a/newlib/libm/math/w_lgamma.c b/newlib/libm/math/w_lgamma.c
> index c07804779..c075a4fc1 100644
> --- a/newlib/libm/math/w_lgamma.c
> +++ b/newlib/libm/math/w_lgamma.c
> @@ -22,6 +22,10 @@
>  #include <reent.h>
>  #include <errno.h>
> 
> +#ifdef _REENT_THREAD_LOCAL
> +_Thread_local int _tls_gamma_signgam;
> +#endif
> +
>  #ifndef _DOUBLE_IS_32BITS
> 
>  #ifdef __STDC__
> diff --git a/newlib/newlib.hin b/newlib/newlib.hin
> index 30f59ddba..e87a5eabb 100644
> --- a/newlib/newlib.hin
> +++ b/newlib/newlib.hin
> @@ -406,6 +406,10 @@
>     restricted storage. */
>  #undef _WANT_REENT_SMALL
> 
> +/* Define to enable thread-local storage objects as a replacment for struct
> +   _reent members. */
> +#undef _WANT_REENT_THREAD_LOCAL
> +
>  /* Register application finalization function using atexit. */
>  #undef _WANT_REGISTER_FINI
> 
> --
> 2.35.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.