This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: why "Reentrant covers for OS subroutines" use global errno?
On 08/09/2011 05:31 AM, Can Finner wrote:
Hi,
I am studying the reentrancy mechanism in newlib/libgloss, and read
several threads in newlib mail archive,
I still cannot understand following question.
Why do "Reentrant covers for OS subroutines"(in libc/reent/) use
global errno variable with codes like:
#include<errno.h>
#undef errno
extern int errno;
The __getreent() support is rather new in the scheme of things for newlib.
Historically, the reentrant wrappers in libc/reent were done to wrap
non-reentrant syscalls.
From libc/include/reent.h:
The target may provide the needed syscalls by any of the following:
1) Define the reentrant versions of the syscalls directly.
(eg: _open_r, _close_r, etc.). Please keep the namespace clean.
When you do this, set "syscall_dir" to "syscalls" and add
-DREENTRANT_SYSCALLS_PROVIDED to newlib_cflags in configure.host.
2) Define namespace clean versions of the system calls by prefixing
them with '_' (eg: _open, _close, etc.). Technically, there
won't be
true reentrancy at the syscall level, but the library will be
namespace clean.
Number 2 applies here.
The non-reentrant syscalls don't take the extra parameter to pass them
the reentrancy structure so the answer at the time was to have them set
the external int errno. The wrapper sets the newlib-ized version of
errno when an error occurs.
Hence there is not true reentrancy at the syscall level.
If desired, arm can go the route of 1) whereby it provides _r versions
of the syscalls which then can access the reentrancy structure at will
since it is passed
OR
the syscalls in arm libgloss can be modified to access the _REENT macro
in the case of SINGLE_THREAD and/or arm can provide a getreent()
function. In these cases, the syscalls would set _errno directly and
not touch the value of int errno on an error condition. The wrapper
will then not use the value of int errno and it will be reentrant.
-- Jeff J.
It is said the system can achieve reentrancy by implementing its own
__getreent function,
defining macro __DYNAMIC_REENT__ and implementing libgloss with
errno.h directly.
However, with routines in libc/reent directory, system won't be
reentrant unless defining macro
REENTRANT_SYSCALLS_PROVIDED and implementing _r versions of syscalls
in libgloss.
Think about calling sequence of a simple case for arm:
fwrite --> __swrite --> _write_r(in libc/reent) --> _write(in libgloss/arm)
routine _write_r uses global errno variable, which breaks the
reentrancy in the calling sequence.
Did I misunderstand the reentrancy mechanism in newlib/libgloss or
something wrong?
Please help, thanks in advance.