This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
Re: _REENT_ONLY question
- From: "J. Johnston" <jjohnstn at redhat dot com>
- To: "Artem B. Bityuckiy" <abityuckiy at yandex dot ru>
- Cc: newlib at sources dot redhat dot com
- Date: Thu, 27 Nov 2003 11:59:27 -0500
- Subject: Re: _REENT_ONLY question
- Organization: Red Hat Inc.
- References: <3FC5F6B3.6070304@yandex.ru>
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.