This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Re: Question about the highly optimized aspects of libc implementation
- From: Florian Weimer <fweimer at redhat dot com>
- To: Will Hawkins <whh8b at virginia dot edu>
- Cc: libc-help at sourceware dot org
- Date: Mon, 4 Dec 2017 13:15:17 +0100
- Subject: Re: Question about the highly optimized aspects of libc implementation
- Authentication-results: sourceware.org; auth=none
- References: <CAE+MWFsT5vu4yW0zDKgyinZky=2s-i2wzK7N-fnKuQP0kGQ_Bw@mail.gmail.com> <fde62ca9-cc75-d065-3ab3-25b627e0f12d@redhat.com> <CAE+MWFuN091txG2F-eTQ=wi_bL7GhWALoJhNoThUYMzg5s7-zQ@mail.gmail.com>
On 12/04/2017 02:15 AM, Will Hawkins wrote:
The fcntl implementation calls va_arg on a variadic argument which might not
actually exist. The syscall function does something similar (but it is
actually implemented in machine code, so it's less of a problem).
Are you referring to
...
int
__libc_fcntl (int fd, int cmd, ...)
{
va_list ap;
void *arg;
va_start (ap, cmd);
arg = va_arg (ap, void *);
va_end (ap);
...
from sysdeps/unix/sysv/linux/fcntl.c?
Right, this is what I had in mind.
The NSS internals in general and getaddrinfo in particular call functions
through a mis-matching function pointer (with an additional argument added,
or with a void * argument where the function is defined with a concrete
function pointer).
Are you referring to, for example,
if (fct != NULL)
{
if (req->ai_family == AF_INET6
|| req->ai_family == AF_UNSPEC)
{
gethosts (AF_INET6, struct in6_addr);
no_inet6_data = no_data;
inet6_status = status;
}
Yes, per the comment above:
if (fct == NULL)
/* We are cheating here. The gethostbyname2_r
function does not have the same interface as
gethostbyname3_r but the extra arguments the
latter takes are added at the end. So the
gethostbyname2_r code will just ignore them. */
fct = __nss_lookup_function (nip, "gethostbyname2_r");
from sysdeps/posix/getaddrinfo.c where gethosts uses DL_CALL_FCT to
invoke fct as if it were a function that returned void* and with an
additional void* parameter as a result of the call through
_dl_mcount_wrapper_check?
I haven't considered this. I meant the pointer assignment I quoted above.
What you've given me is great! However, if there are other interesting
ones, I'd love to hear them! I love seeing the /expert/ uses of the C
language for learning. You are all amazing craftpersons -- it's great
to watch you work.
Oh, I expected you were doing research on deliberate use of non-standard
constructs. We get such queries from time to time.
The examples I quoted can hardly be considered “expert uses”. They are
just the historically chosen approach. I doubt we would add such code
today, maybe with the exception of the fcntl case.
In any case, these a truly bad examples, and we only get away with this
because the C library is essentially part of the C implementation. For
general-purpose programming, these practices are harmful, and we are
gradually removing problematic code from glibc, too.
Are there any places where, I know this sounds crazy, but functions
are invoked with push/jump (or straight jumps) because, for instance
they are tail calls or somehow the return address is known statically?
In general, the compiler does this automatically if feasible. If we
need this optimization (say for clone/vfork), I think we implement the
functions involved in assembler.
Thanks,
Florian