Some questions on reentrancy, __DYNAMIC_REENT__ and _impure_ptr

Dave Nadler drn@nadler.com
Thu Apr 1 14:48:05 GMT 2021


On 4/1/2021 12:58 AM, Nick wrote:
> Hi,
>
> I've been trying to enable reentrancy of newlib on a home brew kernel 
> for the x86 platform and have some questions on how various pieces all 
> fits together.

Oy, we can never have enough kernels ;-)

I'm not familiar with all the possible permutations.
In FreeRTOS, the scheduler simply switches _impure_ptr before each 
context switch.
This is perfectly thread safe given:
- the read/write of this ptr is atomic (true on the architectures I 
know), and
- no ISR use of anything in the RTL requiring this (ie no malloc, 
strtok, etc. in ISR)
Here's the code from FreeRTOS:

         #if ( configUSE_NEWLIB_REENTRANT == 1 )
         {
             /* Switch Newlib's _impure_ptr variable to point to the _reent
             structure specific to this task.
             See the third party link 
http://www.nadler.com/embedded/newlibAndFreeRTOS.html
             for additional information. */
             _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
         }
         #endif /* configUSE_NEWLIB_REENTRANT */

I hope that clears up all your questions below!
Best Regards, Dave



> Implemented __getreent () to return a private copy of struct reent, 
> and also hard coded __DYNAMIC_REENT__ and GETREENT_PROVIDED in 
> sys/config.h to rule out any issue of passing in via build CFLAGS or 
> the CFLAGS in configure.host. Things including errno seem to work but 
> not totally making sense.
>
> As many library functions are still accessing the reent structure 
> using _impure_ptr instead of calling my __getreent () function, for 
> example, the CHECK_INIT (_REENT, fp) at the beginning of __swsetup_r 
> (struct _reent *ptr, register FILE * fp).
>
> Questions:
>
> 1. Are the library functions expected to still use _impure_ptr instead 
> of calling __getreent () when both __DYNAMIC_REENT__ and 
> GETREENT_PROVIDED are hard coded in sys/config.h?
>
> If so, how do they provide reentrancy? Since _impure_ptr is a global 
> pointer visible to all threads and threads can easily step on each 
> other's toes trying to change fields in the reent structure pointed to 
> by _impure_ptr concurrently.
>
> If not, what other MACROs or changes should I make so that all the 
> library functions all use __getreent () instead of _impure_ptr? Is it 
> okay to set _impure_ptr to a bad value such as NULL in this case, in 
> order to catch any unintended access?
>
> 2. in the documentation on https://sourceware.org/newlib/, the 
> following is mentioned as needed for syscalls stubs to return errno:
>
> #include <errno.h>
> #undef errno
> extern int errno;
>
> If I do include this part, all the syscalls stubs seem to do when they 
> assign values to errno is setting the global int errno; inside 
> reent.c. As user code built against the library don’t read out that 
> integer but instead calls __(), errno set by syscall stubs can't be 
> read out by user code.
>
> If on the other hand I don’t include this part before my syscall 
> stubs, the errno set by them do seem to work as they also set the copy 
> in reent structures. What might I have missed here?
>
> 3. There were some old discussions about manually changing _impure_ptr 
> at each context switch. But I’m wondering about the validity of such a 
> method since it seems like a really clumsy maneuver for kernel code at 
> CPL0 to reach into user space belonging to different binaries to 
> change a global pointer. What's more, if manually changing _impure_ptr 
> at each context switch is needed, then what would be the purpose of 
> __DYNAMIC_REENT__, GETREENT_PROVIDED and implementing a __getreent () 
> to get a thread local version?
>
> 4. Is _global_impure_ptr thread safe? It is a bit concerning as it 
> seems to be pointing to the same copy of impure_data that some 
> libraries calls would access, and even if I try to change _impure_ptr 
> at each context switch, some threads might still be accessing 
> _global_impure_ptr concurrently?
>
> 5. There were also old discussions about having to provide mutex for 
> malloc, is this still the case for newer versions of newlib like 4.10?
>
> Thanks!
> Nick


-- 
Dave Nadler, USA East Coast voice (978) 263-0097, drn@nadler.com, Skype
  Dave.Nadler1



More information about the Newlib mailing list