GLib "next cycle" update

hi everyone,

I've torn through a great deal of what I wrote about in "GLib plans for
next cycle" email.  Changes are on master.

I'm presently working on the "wip/mutexes" branch.  There are two
somewhat-related efforts on this branch:

First, I'm trying to slay bug #70598 by deprecating GStaticMutex and
creating a GMutex that you can do:

  GMutex mutex = G_MUTEX_INIT;

and the same for GCond while we're at it and GPrivate to a somewhat more
limited extent (for GLib internal use only, at present).

The benefit here is that we can have mutexes and condition variables
without any memory allocation at all, which is good for avoiding
initialisation dependency cycles inside libglib (where gmem depends on a
GMutex, but GMutexes are allocated with gmem, for example).

The most controversial patch here so far is this one:

which could be seen as causing an ABI Break for glib-using libraries
that export locks defined as a G_DEFINE_LOCK as part of their public
ABI.  That's unlikely.

It's also an API (but not ABI) break if you were trying to use the
undocumented G_LOCK_NAME macro (as GCancellable is doing, and thus
needed to be fixed).  This could be considered a bug in the application
and is easy to fix.

Second, I'm trying to nuke the few remaining reasons that
g_thread_init() is required at all.  The static GMutex/GCond/GPrivate
code is making this a bit easier, but there are some performance

In particular, in the 'likely' case, gslice goes to substantial pains to
avoid any cross-thread synchronisation.  This is incompatible with
implicit initialisation in threaded contexts.  There are approximately
three ways that I can think of to address this:

 - suck it up and do a proper thread-safe implicit initialisation

   This is probably no performance decrease on Intel (where we have
   somewhat strict ordering guarantees and can probably avoid a fence). 
   It will definitely require fences on some platforms, however.

 - initialise on the first g_thread_create() call

   This seems like it would avoid any chance of races in gslice
   initialisation but it means that we wouldn't be safe with respect to
   threads that weren't created by GLib (like some asynchronous
   libraries do for callbacks).

 - use a __attribute__((constructor)) approach

   I have a patch here to introduce this concept as a quick hack:

   and two uses of it:

   For the record, I think that this is a somewhat inelegant solution.
   Maybe it's our best choice, though, given the constraints.  I know
   some others want to make use of this, and maybe we could even
   consider making the API public (and cleaning it up).

   I have doubts that we can ever support this everywhere in a portable
   way but we can probably get pretty reasonable coverage.  Matthias
   also raised some concern about the undefined order in which the
   constructors could be called (which means that we might have to
   refrain from calling gslice from other constructors, for example,
   since gslice may not have been initialised yet).

   A couple of solutions to that:

     - use the (priority) field of GCC

     - use internal rigging to ensure dependent inits are called first
       or just use one big initialisation function that does it in the
       right order

     - make the ENSURE macro do a thread-unsafe initialisation check
       even in the case that we support constructors so that we catch
       these sorts of problems.  This would be safe* because the ctors
       are always running at a time when we can be guaranteed the code
       is only being accessed by a single thread.


* I can, in theory, imagine some truly absurd scenarios where this may
not be true.  They involve a CPU speculating reads from a library for
which dlopen() has yet to return a handle on another CPU.  I'm am not
overly concerned.

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]