why "Reentrant covers for OS subroutines" use global errno?

David Paterson dnpaterson@gmail.com
Tue Aug 9 17:04:00 GMT 2011


On Tue, Aug 9, 2011 at 11:13 AM, Can Finner <can.finner@gmail.com> wrote:
>> Hi Can,
>>
>> "_write_r" is the reentrant version and shouldn't be accessing errno
>> as a global.
>>
>> It should be defined to have an additional parameter over the standar
>> "write" which is
>> a pointer to a "_reent" structure, which contains the current errno, e.g. :-
>>
>>    ptr->_errno = <some_error_value>;
>>
>> Have a look at the definitions in newlib/libc/reent.
>>
> Thanks for explain.
>
> well the implementation of libc/reent/writer.c is like:
>
> -------------------------------------------------------
> #ifndef REENTRANT_SYSCALLS_PROVIDED
>
> /* We use the errno variable used by the system dependent layer.  */
> #undef errno
> extern int errno;
>
>
> _ssize_t
> _DEFUN (_write_r, (ptr, fd, buf, cnt),
>     struct _reent *ptr _AND
>     int fd _AND
>     _CONST _PTR buf _AND
>     size_t cnt)
> {
>  _ssize_t ret;
>
>  errno = 0;
>  if ((ret = (_ssize_t)_write (fd, buf, cnt)) == -1 && errno != 0)
>    ptr->_errno = errno;
>  return ret;
> }
>
> #endif /* ! defined (REENTRANT_SYSCALLS_PROVIDED) */
> -------------------------------------------------------
> My mis-understanding, but
>
> Seems if _write and other syscalls only access errno in reent
> structure, the global errno won't be set forever and the condition
> always be false.
> So what's the global errno and if statement for?
>
> Thanks.
> --
> Regards.
>

In a reentrant build "errno" shouldn't be a variable, but a macro which expands
to access the current _reent structure's _errno field.

That code is indeed a bit confusing, and I'm not sure if it just reassigns the
value to itself, or if there are in fact two different _reent structs.

I'm kind of learning about this as well at the moment, as I'm doing a port to a
Sparc-based system.  There's a lot to learn...

Cheers,

David P.



More information about the Newlib mailing list