Support _REENT_THREAD_LOCAL Newlib configuration

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.
This commit is contained in:
Matt Joyce
2022-05-23 12:27:56 +02:00
committed by Sebastian Huber
parent 57a569efe1
commit 6d4b390f99
7 changed files with 42 additions and 18 deletions

View File

@@ -57,7 +57,8 @@
extern "C" { extern "C" {
#endif #endif
#ifdef _CONFIGURE_ENABLE_NEWLIB_REENTRANCY #if defined(_CONFIGURE_ENABLE_NEWLIB_REENTRANCY) && \
!defined(_REENT_THREAD_LOCAL)
struct _reent *__getreent( void ) struct _reent *__getreent( void )
{ {
return _Thread_Get_executing()->libc_reent; return _Thread_Get_executing()->libc_reent;

View File

@@ -159,7 +159,8 @@ struct Thread_Configured_control {
#if CONFIGURE_MAXIMUM_THREAD_NAME_SIZE > 1 #if CONFIGURE_MAXIMUM_THREAD_NAME_SIZE > 1
char name[ CONFIGURE_MAXIMUM_THREAD_NAME_SIZE ]; char name[ CONFIGURE_MAXIMUM_THREAD_NAME_SIZE ];
#endif #endif
#ifdef _CONFIGURE_ENABLE_NEWLIB_REENTRANCY #if defined(_CONFIGURE_ENABLE_NEWLIB_REENTRANCY) && \
!defined(_REENT_THREAD_LOCAL)
struct _reent Newlib; struct _reent Newlib;
#endif #endif
}; };
@@ -175,7 +176,8 @@ const Thread_Control_add_on _Thread_Control_add_ons[] = {
), ),
offsetof( Thread_Configured_control, API_RTEMS ) offsetof( Thread_Configured_control, API_RTEMS )
} }
#ifdef _CONFIGURE_ENABLE_NEWLIB_REENTRANCY #if defined(_CONFIGURE_ENABLE_NEWLIB_REENTRANCY) && \
!defined(_REENT_THREAD_LOCAL)
, { , {
offsetof( offsetof(
Thread_Configured_control, Thread_Configured_control,

View File

@@ -96,10 +96,16 @@ extern int malloc_info(Heap_Information_block *the_info);
/* /*
* Prototypes required to install newlib reentrancy user extension * Prototypes required to install newlib reentrancy user extension
*/ */
#ifdef _REENT_THREAD_LOCAL
#define _NEWLIB_CREATE_HOOK NULL
#else
bool newlib_create_hook( bool newlib_create_hook(
rtems_tcb *current_task, rtems_tcb *current_task,
rtems_tcb *creating_task rtems_tcb *creating_task
); );
#define _NEWLIB_CREATE_HOOK newlib_create_hook
#endif
void newlib_terminate_hook( void newlib_terminate_hook(
rtems_tcb *current_task rtems_tcb *current_task
@@ -107,15 +113,15 @@ void newlib_terminate_hook(
#define RTEMS_NEWLIB_EXTENSION \ #define RTEMS_NEWLIB_EXTENSION \
{ \ { \
newlib_create_hook, /* rtems_task_create */ \ _NEWLIB_CREATE_HOOK, /* thread_create */ \
0, /* rtems_task_start */ \ NULL, /* thread_start */ \
0, /* rtems_task_restart */ \ NULL, /* thread_restart */ \
0, /* rtems_task_delete */ \ NULL, /* thread_delete */ \
0, /* task_switch */ \ NULL, /* thread_switch */ \
0, /* task_begin */ \ NULL, /* thread_begin */ \
0, /* task_exitted */ \ NULL, /* thread_exitted */ \
0, /* fatal */ \ NULL, /* fatal */ \
newlib_terminate_hook /* thread terminate */ \ newlib_terminate_hook /* thread_terminate */ \
} }
typedef struct { typedef struct {

View File

@@ -921,8 +921,12 @@ struct _Thread_Control {
*/ */
Context_Control_fp *fp_context; Context_Control_fp *fp_context;
#endif #endif
#ifndef _REENT_THREAD_LOCAL
/** This field points to the newlib reentrancy structure for this thread. */ /** This field points to the newlib reentrancy structure for this thread. */
struct _reent *libc_reent; struct _reent *libc_reent;
#endif
/** This array contains the API extension area pointers. */ /** This array contains the API extension area pointers. */
void *API_Extensions[ THREAD_API_LAST + 1 ]; void *API_Extensions[ THREAD_API_LAST + 1 ];

View File

@@ -15,8 +15,10 @@
#if defined(RTEMS_NEWLIB) #if defined(RTEMS_NEWLIB)
#include <sys/reent.h> #include <sys/reent.h>
#ifndef _REENT_THREAD_LOCAL
struct _reent *__getreent(void) struct _reent *__getreent(void)
{ {
return _GLOBAL_REENT; return _GLOBAL_REENT;
} }
#endif #endif
#endif

View File

@@ -29,6 +29,7 @@
#include <rtems/libcsupport.h> #include <rtems/libcsupport.h>
#include <rtems/score/threadimpl.h> #include <rtems/score/threadimpl.h>
#ifndef _REENT_THREAD_LOCAL
bool newlib_create_hook( bool newlib_create_hook(
rtems_tcb *current_task RTEMS_UNUSED, rtems_tcb *current_task RTEMS_UNUSED,
rtems_tcb *creating_task rtems_tcb *creating_task
@@ -38,12 +39,17 @@ bool newlib_create_hook(
return true; return true;
} }
#endif
void newlib_terminate_hook( void newlib_terminate_hook(
rtems_tcb *current_task rtems_tcb *current_task
) )
{ {
#ifdef _REENT_THREAD_LOCAL
_reclaim_reent(NULL);
#else
_reclaim_reent(current_task->libc_reent); _reclaim_reent(current_task->libc_reent);
#endif
} }
#endif #endif

View File

@@ -43,6 +43,10 @@
#include "tmacros.h" #include "tmacros.h"
#ifndef _REENT_CLEANUP
#define _REENT_CLEANUP(ptr) ((ptr)->__cleanup)
#endif
const char rtems_test_name[] = "NEWLIB 1"; const char rtems_test_name[] = "NEWLIB 1";
static const char stdio_file_path[] = "/stdio-file"; 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) static void stdio_file_worker(rtems_task_argument arg)
{ {
test_context *ctx = &test_instance; test_context *ctx = &test_instance;
struct _reent *reent = _REENT;
FILE *output; FILE *output;
char buf[1] = { 'x' }; char buf[1] = { 'x' };
size_t n; size_t n;
@@ -137,7 +140,7 @@ static void stdio_file_worker(rtems_task_argument arg)
test_rand(); test_rand();
test_lrand48(); test_lrand48();
rtems_test_assert(reent->__cleanup == NULL); rtems_test_assert(_REENT_CLEANUP(_REENT) == NULL);
output = stdout = fopen(&stdio_file_path[0], "r+"); output = stdout = fopen(&stdio_file_path[0], "r+");
rtems_test_assert(stdout != NULL); 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. * 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(fflush(stdout) == 0);
rtems_test_assert(reent->__cleanup != NULL); rtems_test_assert(_REENT_CLEANUP(_REENT) != NULL);
rtems_test_assert(stdout == output); rtems_test_assert(stdout == output);
n = fwrite(&buf[0], sizeof(buf), 1, stdout); n = fwrite(&buf[0], sizeof(buf), 1, stdout);