This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[PATCH] Add and use _REENT_GLOBAL_ATEXIT
- From: Sebastian Huber <sebastian dot huber at embedded-brains dot de>
- To: newlib at sourceware dot org
- Date: Sun, 28 Apr 2013 19:56:05 +0200
- Subject: [PATCH] Add and use _REENT_GLOBAL_ATEXIT
This is a patch for discussion. It is highly experimental and should
not be committed.
The new define _REENT_GLOBAL_ATEXIT can be used to select a new third
variant of reentrancy structures. The struct _reent is used for
thread-local state and the struct _reent_global is used for the global
system state. The global system state contains atexit() support used by
__atexit.c and __call_atexit.c.
On PowerPC RTEMS the sizeof(struct _reent) drops down from 1088 bytes to
640 bytes. The sizeof(struct _reent_global) is 1048 bytes, since some
unused fields were removed.
The new struct _reent has no gimmicks to make binary compatibility
easier.
---
newlib/libc/include/sys/config.h | 5 ++
newlib/libc/include/sys/reent.h | 175 ++++++++++++++++++++++++++++++++++--
newlib/libc/reent/impure.c | 6 ++
newlib/libc/reent/reent.c | 7 +-
newlib/libc/stdlib/__atexit.c | 8 +-
newlib/libc/stdlib/__call_atexit.c | 4 +-
6 files changed, 191 insertions(+), 14 deletions(-)
diff --git a/newlib/libc/include/sys/config.h b/newlib/libc/include/sys/config.h
index a6528b8..b1dbbe3 100644
--- a/newlib/libc/include/sys/config.h
+++ b/newlib/libc/include/sys/config.h
@@ -215,6 +215,7 @@
#endif
#if defined(__rtems__)
+#define _REENT_GLOBAL_ATEXIT
#define __FILENAME_MAX__ 255
#define _READ_WRITE_RETURN_TYPE _ssize_t
#endif
@@ -256,4 +257,8 @@
#define _MB_EXTENDED_CHARSETS_WINDOWS 1
#endif
+#if defined(_REENT_SMALL) && defined(_REENT_GLOBAL_ATEXIT)
+#error "invalid _reent configuration"
+#endif
+
#endif /* __SYS_CONFIG_H__ */
diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h
index 7e321e0..e0efc97 100644
--- a/newlib/libc/include/sys/reent.h
+++ b/newlib/libc/include/sys/reent.h
@@ -325,7 +325,7 @@ struct _rand48 {
* reentrant. IE: All state information is contained here.
*/
-#ifdef _REENT_SMALL
+#if defined(_REENT_SMALL)
struct _mprec
{
@@ -575,7 +575,165 @@ extern const struct __sFILE_fake __sf_fake_stderr;
#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_misc->_getdate_err))
#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_signal_buf)
-#else /* !_REENT_SMALL */
+#elif defined(_REENT_GLOBAL_ATEXIT) /* && !_REENT_SMALL */
+
+struct _reent
+{
+ int _errno; /* local copy of errno */
+
+ /* FILE is a big struct and may change over time. To try to achieve binary
+ compatibility with future versions, put stdin,stdout,stderr here.
+ These are pointers into member __sf defined below. */
+ __FILE *_stdin, *_stdout, *_stderr;
+
+ int _inc; /* used by tmpnam */
+ char _emergency[_REENT_EMERGENCY_SIZE];
+
+ int _current_category; /* used by setlocale */
+ _CONST char *_current_locale;
+
+ int __sdidinit; /* 1 means stdio has been init'd */
+
+ void _EXFNPTR(__cleanup, (struct _reent *));
+
+ /* used by mprec routines */
+ struct _Bigint *_result;
+ int _result_k;
+ struct _Bigint *_p5s;
+ struct _Bigint **_freelist;
+
+ /* used by some fp conversion routines */
+ int _cvtlen; /* should be size_t */
+ char *_cvtbuf;
+
+ char * _strtok_last;
+ char _asctime_buf[_REENT_ASCTIME_SIZE];
+ struct __tm _localtime_buf;
+ int _gamma_signgam;
+ __extension__ unsigned long long _rand_next;
+ struct _rand48 _r48;
+ _mbstate_t _mblen_state;
+ _mbstate_t _mbtowc_state;
+ _mbstate_t _wctomb_state;
+ char _l64a_buf[8];
+ char _signal_buf[_REENT_SIGNAL_SIZE];
+ int _getdate_err;
+ _mbstate_t _mbrlen_state;
+ _mbstate_t _mbrtowc_state;
+ _mbstate_t _mbsrtowcs_state;
+ _mbstate_t _wcrtomb_state;
+ _mbstate_t _wcsrtombs_state;
+
+ /* signal info */
+ void (**(_sig_func))(int);
+
+ /* These are here last so that __FILE can grow without changing the offsets
+ of the above members (on the off chance that future binary compatibility
+ would be broken otherwise). */
+ struct _glue __sglue; /* root of glue chain */
+ __FILE __sf[3]; /* first three file descriptors */
+};
+
+struct _reent_global {
+ struct _reent _reent;
+
+ /* atexit stuff */
+ struct _atexit *_atexit; /* points to head of LIFO stack */
+ struct _atexit _atexit0; /* one guaranteed table, required by ANSI */
+};
+
+#define _REENT_INIT(var) \
+ { 0, \
+ &(var).__sf[0], \
+ &(var).__sf[1], \
+ &(var).__sf[2], \
+ 0, \
+ "", \
+ 0, \
+ "C", \
+ 0, \
+ _NULL, \
+ _NULL, \
+ 0, \
+ _NULL, \
+ _NULL, \
+ 0, \
+ _NULL, \
+ _NULL, \
+ "", \
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+ 0, \
+ 1, \
+ { \
+ {_RAND48_SEED_0, _RAND48_SEED_1, _RAND48_SEED_2}, \
+ {_RAND48_MULT_0, _RAND48_MULT_1, _RAND48_MULT_2}, \
+ _RAND48_ADD \
+ }, \
+ {0, {0}}, \
+ {0, {0}}, \
+ {0, {0}}, \
+ "", \
+ "", \
+ 0, \
+ {0, {0}}, \
+ {0, {0}}, \
+ {0, {0}}, \
+ {0, {0}}, \
+ {0, {0}}, \
+ _NULL, \
+ {_NULL, 0, _NULL} \
+ }
+
+#define _REENT_INIT_PTR(var) \
+ { (var) = memset((var), 0, sizeof(*(var))); \
+ (var)->_stdin = &(var)->__sf[0]; \
+ (var)->_stdout = &(var)->__sf[1]; \
+ (var)->_stderr = &(var)->__sf[2]; \
+ (var)->_current_locale = "C"; \
+ (var)->_rand_next = 1; \
+ (var)->_r48._seed[0] = _RAND48_SEED_0; \
+ (var)->_r48._seed[1] = _RAND48_SEED_1; \
+ (var)->_r48._seed[2] = _RAND48_SEED_2; \
+ (var)->_r48._mult[0] = _RAND48_MULT_0; \
+ (var)->_r48._mult[1] = _RAND48_MULT_1; \
+ (var)->_r48._mult[2] = _RAND48_MULT_2; \
+ (var)->_r48._add = _RAND48_ADD; \
+ }
+
+#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 */
+
+#define _REENT_SIGNGAM(ptr) ((ptr)->_gamma_signgam)
+#define _REENT_RAND_NEXT(ptr) ((ptr)->_rand_next)
+#define _REENT_RAND48_SEED(ptr) ((ptr)->_r48._seed)
+#define _REENT_RAND48_MULT(ptr) ((ptr)->_r48._mult)
+#define _REENT_RAND48_ADD(ptr) ((ptr)->_r48._add)
+#define _REENT_MP_RESULT(ptr) ((ptr)->_result)
+#define _REENT_MP_RESULT_K(ptr) ((ptr)->_result_k)
+#define _REENT_MP_P5S(ptr) ((ptr)->_p5s)
+#define _REENT_MP_FREELIST(ptr) ((ptr)->_freelist)
+#define _REENT_ASCTIME_BUF(ptr) ((ptr)->_asctime_buf)
+#define _REENT_TM(ptr) (&(ptr)->_localtime_buf)
+#define _REENT_EMERGENCY(ptr) ((ptr)->_emergency)
+#define _REENT_STRTOK_LAST(ptr) ((ptr)->_strtok_last)
+#define _REENT_MBLEN_STATE(ptr) ((ptr)->_mblen_state)
+#define _REENT_MBTOWC_STATE(ptr)((ptr)->_mbtowc_state)
+#define _REENT_WCTOMB_STATE(ptr)((ptr)->_wctomb_state)
+#define _REENT_MBRLEN_STATE(ptr)((ptr)->_mbrlen_state)
+#define _REENT_MBRTOWC_STATE(ptr)((ptr)->_mbrtowc_state)
+#define _REENT_MBSRTOWCS_STATE(ptr)((ptr)->_mbsrtowcs_state)
+#define _REENT_WCRTOMB_STATE(ptr)((ptr)->_wcrtomb_state)
+#define _REENT_WCSRTOMBS_STATE(ptr)((ptr)->_wcsrtombs_state)
+#define _REENT_L64A_BUF(ptr) ((ptr)->_l64a_buf)
+#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_signal_buf)
+#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_getdate_err))
+
+#else /* !_REENT_SMALL && !_REENT_GLOBAL_ATEXIT */
struct _reent
{
@@ -799,7 +957,7 @@ struct _reent
#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_new._reent._signal_buf)
#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_new._reent._getdate_err))
-#endif /* !_REENT_SMALL */
+#endif /* !_REENT_SMALL && !_REENT_GLOBAL_ATEXIT */
/* 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
@@ -816,7 +974,16 @@ struct _reent
#endif
extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+#ifdef _REENT_GLOBAL_ATEXIT
+extern struct _reent_global *_CONST _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+#define _GLOBAL_REENT (&_global_impure_ptr->_reent)
+#else
extern struct _reent *_CONST _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+#define _GLOBAL_REENT _global_impure_ptr
+#endif
+
+#define _GLOBAL_REENT_ATEXIT (_global_impure_ptr->_atexit)
+#define _GLOBAL_REENT_ATEXIT0 (_global_impure_ptr->_atexit0)
void _reclaim_reent _PARAMS ((struct _reent *));
@@ -835,8 +1002,6 @@ void _reclaim_reent _PARAMS ((struct _reent *));
#endif /* !_REENT_ONLY */
-#define _GLOBAL_REENT _global_impure_ptr
-
#ifdef __cplusplus
}
#endif
diff --git a/newlib/libc/reent/impure.c b/newlib/libc/reent/impure.c
index f5918c8..7ce825b 100644
--- a/newlib/libc/reent/impure.c
+++ b/newlib/libc/reent/impure.c
@@ -20,9 +20,15 @@ extern const struct __sFILE_fake __sf_fake_stdout _ATTRIBUTE ((weak));
extern const struct __sFILE_fake __sf_fake_stderr _ATTRIBUTE ((weak));
#endif
+#ifdef _REENT_GLOBAL_ATEXIT
+static struct _reent_global __ATTRIBUTE_IMPURE_DATA__ impure_data = { _REENT_INIT (impure_data._reent) };
+struct _reent *__ATTRIBUTE_IMPURE_PTR__ _impure_ptr = &impure_data._reent;
+struct _reent_global *_CONST __ATTRIBUTE_IMPURE_PTR__ _global_impure_ptr = &impure_data;
+#else /* !_REENT_GLOBAL_ATEXIT */
static struct _reent __ATTRIBUTE_IMPURE_DATA__ impure_data = _REENT_INIT (impure_data);
#ifdef __CYGWIN__
extern struct _reent reent_data __attribute__ ((alias("impure_data")));
#endif
struct _reent *__ATTRIBUTE_IMPURE_PTR__ _impure_ptr = &impure_data;
struct _reent *_CONST __ATTRIBUTE_IMPURE_PTR__ _global_impure_ptr = &impure_data;
+#endif /* !_REENT_GLOBAL_ATEXIT */
diff --git a/newlib/libc/reent/reent.c b/newlib/libc/reent/reent.c
index 63812db..e9abdaa 100644
--- a/newlib/libc/reent/reent.c
+++ b/newlib/libc/reent/reent.c
@@ -76,7 +76,7 @@ _DEFUN (_reclaim_reent, (ptr),
}
#endif
-#ifdef _REENT_SMALL
+#if defined(_REENT_SMALL)
if (ptr->_emergency)
_free_r (ptr, ptr->_emergency);
if (ptr->_mp)
@@ -89,7 +89,7 @@ _DEFUN (_reclaim_reent, (ptr),
_free_r (ptr, ptr->_asctime_buf);
if (ptr->_atexit && ptr->_atexit->_on_exit_args_ptr)
_free_r (ptr, ptr->_atexit->_on_exit_args_ptr);
-#else
+#elif !defined(_REENT_GLOBAL_ATEXIT)
/* atexit stuff */
if ((ptr->_atexit) && (ptr->_atexit != &ptr->_atexit0))
{
@@ -121,6 +121,7 @@ _DEFUN (_reclaim_reent, (ptr),
}
}
+#if 0
/*
* Do atexit() processing and cleanup
*
@@ -148,4 +149,4 @@ _DEFUN (_wrapup_reent, (ptr), struct _reent *ptr)
if (ptr->__cleanup)
(*ptr->__cleanup) (ptr);
}
-
+#endif /* !0 */
diff --git a/newlib/libc/stdlib/__atexit.c b/newlib/libc/stdlib/__atexit.c
index 4687d00..f0d0646 100644
--- a/newlib/libc/stdlib/__atexit.c
+++ b/newlib/libc/stdlib/__atexit.c
@@ -31,9 +31,9 @@ _DEFUN (__register_exitproc,
__lock_acquire_recursive(__atexit_lock);
#endif
- p = _GLOBAL_REENT->_atexit;
+ p = _GLOBAL_REENT_ATEXIT;
if (p == NULL)
- _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
+ _GLOBAL_REENT_ATEXIT = p = &_GLOBAL_REENT_ATEXIT0;
if (p->_ind >= _ATEXIT_SIZE)
{
#ifndef _ATEXIT_DYNAMIC_ALLOC
@@ -53,8 +53,8 @@ _DEFUN (__register_exitproc,
return -1;
}
p->_ind = 0;
- p->_next = _GLOBAL_REENT->_atexit;
- _GLOBAL_REENT->_atexit = p;
+ p->_next = _GLOBAL_REENT_ATEXIT;
+ _GLOBAL_REENT_ATEXIT = p;
#ifndef _REENT_SMALL
p->_on_exit_args._fntypes = 0;
p->_on_exit_args._is_cxa = 0;
diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c
index 4c45063..8105f23 100644
--- a/newlib/libc/stdlib/__call_atexit.c
+++ b/newlib/libc/stdlib/__call_atexit.c
@@ -78,8 +78,8 @@ _DEFUN (__call_exitprocs, (code, d),
restart:
- p = _GLOBAL_REENT->_atexit;
- lastp = &_GLOBAL_REENT->_atexit;
+ p = _GLOBAL_REENT_ATEXIT;
+ lastp = &_GLOBAL_REENT_ATEXIT;
while (p)
{
#ifdef _REENT_SMALL
--
1.7.10.4