This is the mail archive of the newlib@sources.redhat.com 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]

Re: errno handling in nonreentrant syscalls (fwd)


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


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