_REENT_ONLY question

J. Johnston jjohnstn@redhat.com
Fri Nov 28 21:05:00 GMT 2003


Artem B. Bityuckiy wrote:
> Hello.
> 
> Please, can anybody explain me why _REENT_ONLY macro is needed? For 
> what? Why some functions have on implementation and another have pair 
> with _r postfix, e.g. setlocale() and _setlocale_r(), etc. Several 
> functions have no such pair, e.g. ldiv(). And in all cases (that I've 
> seen) usual functions call _r pair adding _REENT argument. For example 
> 'setlocale(category, locale)' just calls '_setlocale_r(p, category, 
> locale), where p is 'struct _reent'. I can only guess that this is 
> needed if external (not usual Newlib) "multiprocess support subsystem" 
> is used...
> 
> Can anybody explain this and give me some examples when "_r" pairs are 
> really useful/needed?
> 

I'll start with the _r pairs.  They're used to support threading/reentrancy. 
Probably the simplest example is errno.  The storage behind errno is actually 
kept in newlib's reentrancy structure.  Most users don't see this because there 
is a default reentrancy struct set up on their behalf.  If you look in errno.h 
you will see that errno is a macro which calls __errno which you will find in 
libc/errno/errno.c.  The function just references the default reentrancy 
structure and gives back the address of where errno is stored.

Now, imagine you have multiple threads.  You want an errno per thread.  If you 
call a library function in a thread, you don't want another thread to overwrite 
that value or else you won't be able to check the results of your call.

To handle this, we create _r versions of functions where the reentrancy struct 
is passed in.  In a thread, you call the _r versions of appropriate functions 
and they set the errno for the reentrancy struct you are passing in.
There are other such values (e.g. the last token address for strtok).  If a 
function calls another function which has an _r version, it requires an _r 
version as well.  An example of where this is missing is atol, atoi, and your 
new atoll.  As soon as this is checked in, I am going to fix them.  They call 
strtol and strtoll.  These called functions have _r versions because they set 
errno.  Thus, they should have been modified so an _r version exists as well.
Notice in errno.h, there is a __errno_r macro which you can use to get the errno 
for a particular reentrancy struct.

What the _REENT_ONLY flag does is to force the caller to always use the _r 
routines for appropriate functions.  To do this, the default versions are 
ifdef'd out and only the _r versions are exposed.  You can't inadvertently call 
strtok() from a thread because it isn't in the library.  You are forced to call 
_strtok_r and specify the reentrancy struct.  The reason you want this is that 
the default versions are not protected.  If two threads call strtok(), it is a 
race condition for the token address in the reentrancy struct.  This can be 
difficult to debug as any error might only show up at random.

-- Jeff J.




More information about the Newlib mailing list