_REENT_ONLY question

Artem B. Bityuckiy abityuckiy@yandex.ru
Fri Nov 28 21:37:00 GMT 2003

J. Johnston wrote:

> 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.

Thanks Jeff for ** complete ** description!

Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.

More information about the Newlib mailing list