This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]