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