This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: libstdc++ wants clock_gettime without libpthread
- From: Roland McGrath <roland at hack dot frob dot com>
- To: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- Cc: libc-alpha at sourceware dot org, Paolo Carlini <paolo dot carlini at oracle dot com>, Benjamin Kosnik <bkoz at redhat dot com>
- Date: Thu, 18 Oct 2012 17:22:46 -0700 (PDT)
- Subject: Re: libstdc++ wants clock_gettime without libpthread
- References: <CAH6eHdQRyTgkXE7k+UVpaObNTOZf7QF_fNoU-bqbMhfzXxXUDg@mail.gmail.com>
That is a worthy goal and unfortunately it does not have a very simple
solution.
librt unavoidably uses pthread calls because the aio, mq, and timer
interfaces include the (dynamic) possibility of SIGEV_THREAD, which
obviously has to use pthread_create (and could legitimately be used in a
program that didn't make any direct pthread calls itself).
There are several things we could potentially do, but none is without some
kind of complication.
1. Just move clock_* calls into libc.
Pro: That solves the problem for libstdc++ with almost no special effort
at all on the libstdc++ side. If building libstdc++ just uses -lc
-Wl,--as-needed -lrt then it will be compatible with old
installations where you need to get it from librt, and with new
ones where you can get it from libc and won't generate a DT_NEEDED
on librt.so.N (without requiring configure-time checks to influence
the linking details).
Con:
a. It bloats libc.so.N with code, and its permanent ABI with symbols,
that most applications do not need.
b. For all configurations that exist today, we'll still need to have
clock_* symbols in librt.so because of existing binaries' symbol
version bindings. With IFUNC we could do this in a way where
librt.so would not actually duplicate the code and would just resolve
those symbols using libc.so's definitions. (But there are still some
machines where the tools don't support IFUNC at all.)
2. Split librt.so.N into multiple DSOs and make librt.so be a linker script
using GROUP(AS_NEEDED(librt-clock.so.N librt.so.N)).
Pro:
a. No change whatsoever to libstdc++ and just a recompile would result
in optimal DSO dependencies just by building against a new -lrt.
b. Every other applications newly linked with -lrt would get just the
dependencies it actually needs.
Con:
a. Applications or DSOs that use both clock_* and other interfaces from
-lrt would now have an additional DT_NEEDED entry, with its attendant
additional overhead in startup time, symbol searches, and the like in
the dynamic linker, and some additional address space and memory
overhead from rounding-to-page error in the sizes of the two DSOs and
dynamic linker data structures.
b. We'd still need to have clock_* symbols in librt.so.N because of
existing binaries' DT_NEEDED entries and symbol version bindings.
With IFUNC tricks it could avoid any actual code duplication, but
at the cost of librt.so.N having a DT_NEEDED on librt-clock.so.N
and thus all the aforementioned overhead even for applications that
use only some other -lrt interfaces and not clock_* interfaces.
3. Figure out some arcane thing with DT_FILTER or something.
Pro: Potentially avoids the two-DSOs overheads when both aren't really
needed.
Con:
a. Still has the two-DSOs overhead when both are actually used.
b. Uses dynamic linker features that nobody has really used before
and are not well-tested.
c. It might not even be a fit for the semantics of such features such
that it's not actually possible (with today's dynamic linker).
4. Make librt not depend statically on libpthread, but load it dynamically
as needed.
Pro: Avoids libpthread overheads (both generic DSO-loading overheads and
the overheads of enabling locking and so forth) in applications
that don't actually need libpthread--even ones using timer_* et al
interfaces that can't statically be determined not to need it.
Con:
a. We're not really sure how well we support loading libpthread
dynamically, or if it is worth making sure it works.
b. Even if glibc itself supports it perfectly, it would cause things
like libstdc++/libgcc's __gthr_active_p to treat the "dynamically
multi-threaded" case as being single-threaded. That almost certainly
breaks the semantics of some legitimate code using SIGEV_THREAD and
the like (for example C++ code called from a SIGEV_THREAD notifier
function that interacts in some way with C++ code on the main thread).
It would certainly be some work in libstdc++ et al to make such cases
work as they ought to, and it's entirely possible that it's not
really feasible to make them work at all.
Every approach requires some amount of work in glibc, some perhaps a lot of
work, and some require significant work in libstdc++ and elsewhere. Even
if infinite labor were instantaneously available, there is no approach that
doesn't have some downside.
Thanks,
Roland