This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
RE: Reentrant functions & concurrency
- From: "Schwarz, Konrad" <konrad dot schwarz at siemens dot com>
- To: "Jeff Johnston" <jjohnstn at redhat dot com>
- Cc: <newlib at sources dot redhat dot com>
- Date: Tue, 10 Jan 2006 15:09:24 +0100
- Subject: RE: Reentrant functions & concurrency
> -----Original Message-----
> From: Jeff Johnston [mailto:jjohnstn@redhat.com]
[...]
> > Shouldn't there be a _LOCK_T __errno_lock defined
> somewhere, a call to
> > __lock_acquire (__errno_lock) just before the line "errno =
> 0;" and a
> > call to __lock_release (__errno_lock) just before the line "return
> > ret;"?
>
> This is a historical situation. If you look at
> libc/include/reent.h you will see the following comment which
> acknowledges that supplying just underscore versions of
> syscalls won't be truly reentrant at the syscall
> level:
[..]
> Now that there are locks in newlib, adding them as mentioned
> above is a sound idea. There is one modification required.
> x86-linux specifies MISSING_SYSCALL_NAMES and the syscalls
> themselves are reentrant (i.e.
> they use normal errno, not the external one provided). I am
> guessing that RTEMS would be in the same boat. It would be
> useful to be able to turn the errno locking off via a flag (e.g.
> SYSCALLS_USE_REENTRANT_ERRNO) when it is not needed. The
> locking macros would be indirectly specified via macros in a
> local.h header. Would you like me to whip up something or do
> you already have a trial patch to modify?
I pondered this question some more last night. I now believe that the
fiction of "reentrant" system calls in a "non-reentrant" system is
useless: either a system has thread-safe POSIX-style system calls and
solves the problem of a thread-local errno on its own (e.g., Linux), or
it does not; but then it won't have POSIX-style system calls (that use
errno) at all, since that would be broken:
Currently, newlib uses the _<syscall> routines defined in libgloss/*.c
(or libgloss/libnosys/*.c) as its porting layer. On a system without
POSIX-style system calls, this API adds the global variable errno which
needs to be mutex protected across system calls. By mutex protecting
errno, we will have effectively single-threaded the system-call layer:
only a single thread in the system will be able to be "in" a system call
at any one time. E.g.: Thread A calls _read(), which locks errrno and
then waits for user input, thread B calls _gettimeofday(), which blocks,
waiting for the errno lock to become free, until the _read() in thread A
returns. This would not be desirable at all.
Therefore, the porting layer API must be moved "up" one layer, to the
functions defined in newlib/libc/reent/*.c. The API provided by these
routines makes no assumption of a system-wide errno and the problem
disappears.
However, such a change might also require newlib/libc/reent to be moved
to libgloss and probably have wide repercussions on the build system.
What do you think?
Regards,
Konrad Schwarz