[PATCH 2/2] Support _REENT_THREAD_LOCAL Newlib configuration

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jul 13 09:28:40 UTC 2022


From: Matt Joyce <matthew.joyce at embedded-brains.de>

In case the Newlib _REENT_THREAD_LOCAL configuration option is enabled, the
struct _reent is not defined (there is only a forward declaration in
<sys/reent.h>).  Instead, the usual members of struct _reent are available as
dedicatd thread-local storage objects.

Update #4560.
---
 cpukit/include/rtems/confdefs/newlib.h  |  3 ++-
 cpukit/include/rtems/confdefs/threads.h |  6 ++++--
 cpukit/include/rtems/libcsupport.h      | 28 +++++++++++++++----------
 cpukit/include/rtems/score/thread.h     |  4 ++++
 cpukit/libcsupport/src/newlibc_reent.c  |  6 ++++++
 testsuites/libtests/newlib01/init.c     | 11 ++++++----
 6 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/cpukit/include/rtems/confdefs/newlib.h b/cpukit/include/rtems/confdefs/newlib.h
index 96bf850163..fef71a8855 100644
--- a/cpukit/include/rtems/confdefs/newlib.h
+++ b/cpukit/include/rtems/confdefs/newlib.h
@@ -57,7 +57,8 @@
 extern "C" {
 #endif
 
-#ifdef _CONFIGURE_ENABLE_NEWLIB_REENTRANCY
+#if defined(_CONFIGURE_ENABLE_NEWLIB_REENTRANCY) && \
+  !defined(_REENT_THREAD_LOCAL)
   struct _reent *__getreent( void )
   {
     return _Thread_Get_executing()->libc_reent;
diff --git a/cpukit/include/rtems/confdefs/threads.h b/cpukit/include/rtems/confdefs/threads.h
index 503a4b20ec..8e4537f90b 100644
--- a/cpukit/include/rtems/confdefs/threads.h
+++ b/cpukit/include/rtems/confdefs/threads.h
@@ -159,7 +159,8 @@ struct Thread_Configured_control {
   #if CONFIGURE_MAXIMUM_THREAD_NAME_SIZE > 1
     char name[ CONFIGURE_MAXIMUM_THREAD_NAME_SIZE ];
   #endif
-  #ifdef _CONFIGURE_ENABLE_NEWLIB_REENTRANCY
+  #if defined(_CONFIGURE_ENABLE_NEWLIB_REENTRANCY) && \
+    !defined(_REENT_THREAD_LOCAL)
     struct _reent Newlib;
   #endif
 };
@@ -175,7 +176,8 @@ const Thread_Control_add_on _Thread_Control_add_ons[] = {
     ),
     offsetof( Thread_Configured_control, API_RTEMS )
   }
-  #ifdef _CONFIGURE_ENABLE_NEWLIB_REENTRANCY
+  #if defined(_CONFIGURE_ENABLE_NEWLIB_REENTRANCY) && \
+    !defined(_REENT_THREAD_LOCAL)
     , {
       offsetof(
         Thread_Configured_control,
diff --git a/cpukit/include/rtems/libcsupport.h b/cpukit/include/rtems/libcsupport.h
index 212eb16e59..67a09dc2a2 100644
--- a/cpukit/include/rtems/libcsupport.h
+++ b/cpukit/include/rtems/libcsupport.h
@@ -96,27 +96,33 @@ extern int malloc_info(Heap_Information_block *the_info);
 /*
  *  Prototypes required to install newlib reentrancy user extension
  */
+
+#ifdef _REENT_THREAD_LOCAL
+#define _NEWLIB_CREATE_HOOK NULL
+#else
 bool newlib_create_hook(
   rtems_tcb *current_task,
   rtems_tcb *creating_task
 );
+#define _NEWLIB_CREATE_HOOK newlib_create_hook
+#endif
 
 void newlib_terminate_hook(
   rtems_tcb *current_task
 );
 
 #define RTEMS_NEWLIB_EXTENSION \
-{ \
-  newlib_create_hook,     /* rtems_task_create  */ \
-  0,                      /* rtems_task_start   */ \
-  0,                      /* rtems_task_restart */ \
-  0,                      /* rtems_task_delete  */ \
-  0,                      /* task_switch  */ \
-  0,                      /* task_begin   */ \
-  0,                      /* task_exitted */ \
-  0,                      /* fatal        */ \
-  newlib_terminate_hook   /* thread terminate */ \
-}
+  { \
+    _NEWLIB_CREATE_HOOK,  /* thread_create    */ \
+    NULL,                 /* thread_start     */ \
+    NULL,                 /* thread_restart   */ \
+    NULL,                 /* thread_delete    */ \
+    NULL,                 /* thread_switch    */ \
+    NULL,                 /* thread_begin     */ \
+    NULL,                 /* thread_exitted   */ \
+    NULL,                 /* fatal            */ \
+    newlib_terminate_hook /* thread_terminate */ \
+  }
 
 typedef struct {
   uint32_t active_barriers;
diff --git a/cpukit/include/rtems/score/thread.h b/cpukit/include/rtems/score/thread.h
index dd32b51a5f..94eab18ea3 100644
--- a/cpukit/include/rtems/score/thread.h
+++ b/cpukit/include/rtems/score/thread.h
@@ -921,8 +921,12 @@ struct _Thread_Control {
    */
   Context_Control_fp                   *fp_context;
 #endif
+
+#ifndef _REENT_THREAD_LOCAL
   /** This field points to the newlib reentrancy structure for this thread. */
   struct _reent                        *libc_reent;
+#endif
+
   /** This array contains the API extension area pointers. */
   void                                 *API_Extensions[ THREAD_API_LAST + 1 ];
 
diff --git a/cpukit/libcsupport/src/newlibc_reent.c b/cpukit/libcsupport/src/newlibc_reent.c
index 2dccfd0375..ee82f00858 100644
--- a/cpukit/libcsupport/src/newlibc_reent.c
+++ b/cpukit/libcsupport/src/newlibc_reent.c
@@ -29,6 +29,7 @@
 #include <rtems/libcsupport.h>
 #include <rtems/score/threadimpl.h>
 
+#ifndef _REENT_THREAD_LOCAL
 bool newlib_create_hook(
   rtems_tcb *current_task RTEMS_UNUSED,
   rtems_tcb *creating_task
@@ -38,12 +39,17 @@ bool newlib_create_hook(
 
   return true;
 }
+#endif
 
 void newlib_terminate_hook(
   rtems_tcb *current_task
 )
 {
+#ifdef _REENT_THREAD_LOCAL
+  _reclaim_reent(NULL);
+#else
   _reclaim_reent(current_task->libc_reent);
+#endif
 }
 
 #endif
diff --git a/testsuites/libtests/newlib01/init.c b/testsuites/libtests/newlib01/init.c
index 0bb3c4628b..6edae3adbd 100644
--- a/testsuites/libtests/newlib01/init.c
+++ b/testsuites/libtests/newlib01/init.c
@@ -43,6 +43,10 @@
 
 #include "tmacros.h"
 
+#ifndef _REENT_CLEANUP
+#define _REENT_CLEANUP(ptr) ((ptr)->__cleanup)
+#endif
+
 const char rtems_test_name[] = "NEWLIB 1";
 
 static const char stdio_file_path[] = "/stdio-file";
@@ -129,7 +133,6 @@ static void test_lrand48(void)
 static void stdio_file_worker(rtems_task_argument arg)
 {
   test_context *ctx = &test_instance;
-  struct _reent *reent = _REENT;
   FILE *output;
   char buf[1] = { 'x' };
   size_t n;
@@ -137,7 +140,7 @@ static void stdio_file_worker(rtems_task_argument arg)
   test_rand();
   test_lrand48();
 
-  rtems_test_assert(reent->__cleanup == NULL);
+  rtems_test_assert(_REENT_CLEANUP(_REENT) == NULL);
 
   output = stdout = fopen(&stdio_file_path[0], "r+");
   rtems_test_assert(stdout != NULL);
@@ -145,9 +148,9 @@ static void stdio_file_worker(rtems_task_argument arg)
   /*
    * Check newlib's __sinit does not touch our assigned file pointer.
    */
-  rtems_test_assert(reent->__cleanup == NULL);
+  rtems_test_assert(_REENT_CLEANUP(_REENT) == NULL);
   rtems_test_assert(fflush(stdout) == 0);
-  rtems_test_assert(reent->__cleanup != NULL);
+  rtems_test_assert(_REENT_CLEANUP(_REENT) != NULL);
   rtems_test_assert(stdout == output);
 
   n = fwrite(&buf[0], sizeof(buf), 1, stdout);
-- 
2.35.3



More information about the devel mailing list