After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 660561 - small/fast/simple-abi synchronisation primitives
small/fast/simple-abi synchronisation primitives
Status: RESOLVED DUPLICATE of bug 659866
Product: glib
Classification: Platform
Component: gthread
unspecified
Other All
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2011-09-30 13:02 UTC by Allison Karlitskaya (desrt)
Modified: 2011-10-03 01:02 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Allison Karlitskaya (desrt) 2011-09-30 13:02:43 UTC
We now have:
  GMutex, GCond, GRWLock, GRecMutex

They are typedefed to structs containing:
  pthread_mutex_t, pthread_cond_t, pthread_rwlock_t, gpointer

This is causing problems -- particularly in the case of pthread_rwlock_t.  This type doesn't get declared under certain combinations of compiler defines (mostly involving _XOPEN_SOURCE).

The obvious solution to this is to replace the structures with padding bytes and sample the byte value of the _INITIALIZER macro at ./configure type to be used as our own macro.

I'd really like to avoid these awful hacks, though, so I've been thinking about an alternative.

In essence, we would replace each of the above with a small (pointer-sized?) fixed structure type.


GMutex - one pointer size:
  - Linux: we do the same as bitlocks except we avoid the contention counter
           madness by using a second bit within the lock itself

  - Windows: SRWLock fits into one pointer, so use it

  - other: allocate a pointer to a pthread_mutex_t on first use

GCond - one pointer size:
  - Linux: I think it should be possible to implement a condition variable
           directly on futex(2) only using the pointer as a sequence counter
           to detect the race between unlocking the mutex and sleeping on the
           futex.  We may have spurious wakeups, though.

  - Windows: CONDITION_VARIABLE fits into one pointer, so use it

  - other: allocate a pointer to a pthread_cond_t on first use

GRWLock - one pointer size (maybe more):
  - Linux: I think it's possible to implement a reader/writer lock in one
           32bit value, since Windows appears to do exactly this with SRWLock
           but I'm not sure about how fast it will be.  I have some ideas that
           I'm playing with.

  - Windows: SRWLock again

  - other: allocate a pointer to a pthread_rwlock_t

GRecMutex - one pointer size and/or two ints:
  - Linux: we would need one int for storing the thread ID and one for the
           recursion count.  We could sneak a contended bit into the high
           order bit of the TID field for performance reasons.

  - Windows: allocate a pointer to a CONDITION_VARIABLE or try to do something
             clever with a semaphore object?

  - other: allocate a pointer to a pthread_mutex_t and initialize it for
           recursion



I've taken a look at the glibc code and I've really come to the conclusion that our implementation could be _substantially_ faster.  Most of these need only a single atomic integer operation in the uncontended case.  The structures are also much smaller, which is nice.  It's also nicer from an easy-to-maintain ABI standpoint: the structure size is exactly one pointer (or one pointer and two ints, or so on).  Nothing from system headers needs to be involved.

Some concerns:

  - we slightly regress the situation on bsd/solaris/mac by forcing them to
    use pointers to memory that would have to be allocated.

  - it was at least possible to imagine putting a GMutex into shared memory
    and having it work before -- that is a more distant possibility now (due
    to the pointer indirection being a reference to local virtual memory)

  - can we support adaptive mutexes this way?  In all cases, I think yes.

  - will our new Linux implementation be able to handle priority inversion?
    With the new futex 'PI' API, the answer is yes for at least the normal
    mutex and the recursive mutex.  Less sure about the reader/writer lock.
Comment 1 Allison Karlitskaya (desrt) 2011-09-30 13:59:12 UTC
Worth noting that on OpenBSD and FreeBSD, at least, pthread_mutex_t and friends are just NULL-initialised pointers -- we should obviously special-case that situation.

NetBSD is more similar to Linux, but it also has a futex(ish) interface in the form of _lwp_park/unpark().  Not sure I want to get into doing that for every platform, though.
Comment 2 Allison Karlitskaya (desrt) 2011-10-03 01:02:57 UTC

*** This bug has been marked as a duplicate of bug 659866 ***