This is the mail archive of the mailing list for the newlib project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: _REENT_ONLY question

Artem B. Bityuckiy wrote:

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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]