syscalls, libgloss, errno
Vincent Rivière
vincent.riviere@freesbee.fr
Wed Jan 2 21:53:00 GMT 2008
Jeff, many thanks for your answer !
But there are still things I can't understand.
Let's talk about a very simple configuration. The system is single
threaded, so there are no reentrancy issues. The libgloss implementation
is the standard libnosys, which returns ENOSYS in every function call.
I am in the configuration #2 from reent.h :
MISSING_SYSCALL_NAMES is not defined
and syscall_dir=syscalls
REENTRANT_SYSCALLS_PROVIDED is not defined
I want to :
- #include <errno.h>
- call fopen() and find ENOSYS in errno
- call open() and find ENOSYS in errno
1) The case of fopen()
fopen() will call _open_r().
_open_r() is implemented in libc/reent/openr.c and calls _open()
_open() is implemented in libgloss/libnosys/open.c
2) The case of open()
open() is implemented in syscalls/sysopen.c and calls _open()
_open() is implemented in libgloss/libnosys/open.c
So in every case, we end up to _open() in libgloss. Good.
Now, let's talk about errno.
_open(), in libnosys, returns the error code in "extern int errno".
This is not a problem because we are on a single threaded environment.
open() just calls _open().
So open() returns the error code in "extern int errno".
_open_r() calls _open(), and copies the error code from "extern int
errno" to __errno_r(_REENT). That's good.
So _open_r() returns the error code in __errno_r(_REENT).
fopen() calls _open_r(), and doesn't mess errno.
So fopen() returns the error code in __errno_r(_REENT).
The application #include <errno.h> and uses errno.
In errno.h: #define errno (*__errno())
In errno.c: int * __errno () { return &_REENT->_errno; }
So the application finds the error code in __errno_r(_REENT).
Finally :
When the application calls fopen(), it finds the correct error code in
errno.
But when it calls open(), it will not find the error code in errno
(which is actually __errno_r(_REENT)), because open() returns the error
code into "extern int errno" !
The problem is in the implementation of open() and other syscalls in
libc/syscalls/*
If REENTRANT_SYSCALLS_PROVIDED is defined (which is not the case here),
open() calls _open_r() and the error is returned into __errno_r(_REENT))
as expected.
But if REENTRANT_SYSCALLS_PROVIDED is not defined (the case here), it
should call _open() and translate the error from "extern int errno" to
__errno_r(_REENT), just like the implementation of _open_r() does.
Another solution to implement open() would be to unconditionally call
_open_r(), just like fopen().
Another good working example is rename(), when HAVE_RENAME.
rename() (in libc/stdio/rename.c) unconditionally calls _rename_r().
_rename_r() (in libc/reent/renamer.c) calls _rename() and translates the
error from "extern int errno" to __errno_r(_REENT).
_rename() (provided somewhere in the libgloss implementation) returns
the error into "extern int errno".
Conclusion :
Either I misunderstood something, either there is a problem in
syscalls/sys*.c. In the latter case, I provided 2 simple solutions.
NB: I found a discussion about this problem in the list archives.
http://www.cygwin.com/ml/newlib/2001/msg00305.html
--
Vincent Rivière
More information about the Newlib
mailing list