errno

Description

  • In Newlib, the errno in the standard header file <errno.h> is a macro:
/* <errno.h> */

#define errno (*__errno())
extern int *__errno (void);

int * __errno()
{
  return &_REENT->_errno;
}
  • Newlib’s low-level code handles errno in a very peculiar way, undefining errno and then redefining it as a variable, requiring libgloss to provide the variable definition:
/* <newlib/libc/reent/readr.c> */

#undef errno
extern int errno;

_ssize_t
_read_r (struct _reent *ptr,
     int fd,
     void *buf,
     size_t cnt)
{
  _ssize_t ret;

  errno = 0;
  if ((ret = (_ssize_t)_read (fd, buf, cnt)) == -1 && errno != 0)
    ptr->_errno = errno;
  return ret;
}
/* <libgloss/libnosys/read.c> */

#undef errno
extern int errno;

int
_read (int   file,
        char *ptr,
        int   len)
{
  errno = ENOSYS;
  return -1;
}
  • libgloss provides platform-related startup code, I/O support, system functions, etc., where libnosys is a stub implementation;

Porting Method

  • XWOS defines an __errno variable in each thread object structure and re-implements the int * __errno(void) function, returning the address of the current thread object’s __errno:
int * __errno(void)
{
        xwos_thd_d thdd = xwos_cthd_self();
        return &thdd.thd->osthd.libc.error_number;
}
  • When using the errno macro from <errno.h>, the thread’s own __errno can be obtained, no longer depending on libgloss.