This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
Re: errno handling in nonreentrant syscalls (fwd)
- To: "J. Johnston" <jjohnstn at cygnus dot com>
- Subject: Re: errno handling in nonreentrant syscalls (fwd)
- From: Joachim Falk <jfalk at netxpress dot de>
- Date: Sat, 26 May 2001 07:36:50 +0200 (CEST)
- Cc: newlib at sources dot redhat dot com
- Reply-To: Joachim Falk <joachim dot falk at gmx dot de>
On Fri, 25 May 2001, J. Johnston wrote:
> Joachim Falk wrote:
> >
> > [ SNIP ]
> >
> > Here _read is called directly without any wrapper code to
> > store global errno into _REENT->_errno
> > => Assume _read stores errno into _REENT->_errno itself
> >
> > [ SNIP ]
> >
> > into ptr->_errno
> > => Assume _read stores errno into global errno and not _REENT->_errno
> >
> > What gives it cannot be both true !!
>
> You're right. It's a bit of a mess caused by not being consistent in the past. The system calls
> are not supplied by newlib and are either in libgloss, provided in a bsp library, or the OS provides
> them. A number of libgloss implementations simply set the external errno value in a common trap
> routine. Some implementations use some C code which include errno.h and set errno that way.
> Already you can see there is a discrepancy in how newlib should handle this.
>
> I think the first step is to create a new flag that states whether the non-reentrant system calls
> use an external errno or the C library errno from errno.h. This allows us to dual-path the code and
> at least makes it possible to hook up to which ever system libgloss is using.
>
> As well, it makes sense to go through the library and change all direct errno references to use
> __errno_r() instead of ptr->_errno. Currently, __errno_r() is a macro which should be changed to be
> a function in libc/errno/errno.c. This allows us to override the function when necessary and
> specify where the errno values come from.
| I think the first step is to create a new flag that states whether
| the non-reentrant system calls use an external errno or the C library
| errno from errno.h.
NOREENTRANT_SYSCALLS_GLOBALERRNO
check done that
| As well, it makes sense to go through the library and change all
| direct errno references to use __errno_r() instead of ptr->_errno
check done that
| Currently, __errno_r() is a macro which should be changed to be
| a function in libc/errno/errno.c. This allows us to override the
| function when necessary and specify where the errno values come from.
providing an __errno function is of no use
/*
* errno is not a global variable, because that would make using it
* non-reentrant. Instead, it is __errno_r(_REENT)
*
* A function __errno witch returns the address of errno
* won't work when replace by user code because
* most functions in newlib are defined as there
* reentren version _xxxx_r and the nonreentrant
* simply is the reentrant version called with
* _REENT as their first argument
* => the nonreentrant version will use
* __errnor_r(_REENT) as their errno var
* and not (*__errno())
* => if it wont work we can kill it
*/
providing an __errno_r function is a sollution for errno only
and it is more nonstandard than __errno __errno_location and
how they are all named in the various unixes out there.
Well I suggest to go consistent and to provide a __impure_ptr_location
#ifndef _REENT_ONLY
# define _REENT (*__impure_ptr_location())
extern int *__impure_ptr_location _PARAMS ((void));
#endif
> Joachim Falk Wrote:
> > case 3:
> > syscall dispatching via xxxx we have -DMISSING_SYSCALL_NAMES
> > if read stores errno into _REENT->_errno all is well
> >
> > but if read stores errno into a global errno we are screwd
> > the errno witch I get from
> > #include <errno.h> of newlib
> > is in fact _REENT->_errno so I cant get the errno from
> > my system call !!!!
> >
> > If I alter sys/errno.h of newlib to point to global errno
> > I get the errno values from my system calls
> > but not from newlib intern stuff witch still uses
> > _REENT->_errno in most cases see perror and consorts
cat libc/include/sys/_errno.h
.
. [ SNIP ]
.
#define __errno_nomagic_r(ptr) ((ptr)->_errno)
#if defined(MISSING_SYSCALL_NAMES) && \
defined(NOREENTRANT_SYSCALLS_GLOBALERRNO)
/*
* if we have MISSING_SYSCALL_NAMES we use
* the provided syscalls without underscore
* => there is no wrapper
* => if these syscalls use a global errno
* (NOREENTRANT_SYSCALLS_GLOBALERRNO)
* we must get them from global errno
* into _REENT->_errno.
*/
# define __errno_r(ptr) (*__errno_magic_r(ptr))
extern int *__errno_magic_r _PARAMS ((struct _reent *));
#else
/* no magic needed */
# define __errno_r(ptr) __errno_nomagic_r(ptr)
#endif
cat libc/errno/errno.c
/* The errno variable is stored in the reentrancy structure. */
#include <sys/reent.h>
#include <sys/errno.h>
#ifdef NOREENTRANT_SYSCALLS_GLOBALERRNO
/*
* we need a global errno define it here
*/
# undef errno
int errno;
[
I changed the
int errno;
declaration in ./libc/reent/sbrkr.c to
extern int errno;
This should eliminate the missing errno reference
if MALLOC_PROVIDED is defined as well as
to move the errno declaration into a place
where it should be:
errno.c
]
# ifdef MISSING_SYSCALL_NAMES
/*
* if we have MISSING_SYSCALL_NAMES we use
* the provided syscalls without underscore
* => there is no wrapper
* => if these syscalls use a global errno
* (NOREENTRANT_SYSCALLS_GLOBALERRNO)
* we must get them from global errno
* into _REENT->_errno.
*/
int *
__errno_magic_r (ptr)
struct _reent *ptr;
{
if ( errno != 0 && ptr == _REENT ) {
/* move global errno into _REENT->_errno */
__errno_nomagic_r(ptr) = errno;
errno = 0;
}
return &__errno_nomagic_r(ptr);
}
# endif
#endif
> I think we should just assume that the <errno.h> errno will be used.
> If not, the machine/system should provide an appropriate override for
> __errno() / __errno_r().
NOREENTRANT_SYSCALLS_GLOBALERRNO
must be defined to indicate that nonreentrant syscalls _xxxx or xxxx use
a global errno. This means default is to assume they use _REENT->_errno
whitch is errno from errno.h
Comment suggestions ?
MfG
Joachim Falk