[ANNOUNCE] libxshmfence 1.0

Mark Kettenis mark.kettenis at xs4all.nl
Sun Nov 3 12:00:54 CET 2013


> From: Keith Packard <keithp at keithp.com>
> Date: Sat, 02 Nov 2013 00:39:40 -0700
> 
> Alan Coopersmith <alan.coopersmith at oracle.com> writes:
> 
> > What about platforms which don't have <linux/futex.h> ?
> 
> I looked into alternate synchronization mechanisms; I couldn't figure
> out how to use standard pthread APIs to provide the desired semantics.
> 
> Here's the detailed write up I did that describes the SyncFence
> semantics and how those map directly to Linux Futexes:
> 
>         http://keithp.com/blogs/Shared_Memory_Fences/
> 
> If you can figure out how to build this with pthread mutexes and/or
> semaphores, then we could create a version of xshmfence that worked
> using regular pthread functions. As I understand it, pthread
> synchronization primitives are supposed to work across processes that
> share memory, even if they use different virtual addresses to reference
> the same object.

This requires the "Thread Process-Shared Synchronization" POSIX
option, which isn't implemented everywhere.  Linux and Solaris have
them implemented, the BSD's (including MacOS X) don't provide this
optional extension.

On OpenBSD we've been discussing adding the process-shared semantics
for semaphores.  Once the required kernel modifications are in, we
should be able to have process-shared mutexes and condition variables
as well.

Anyway, your code below isn't actually turning on the process-shared
functionality for the mutexes and condition variables.  This needs to
be done by using appropriate attributes objects, setting the
process-shared attribute using pthread_mutexattr_setpshared() and
pthread_condattr_setpshared() and using the attributes to initialize
the mutexes and condition variables.  I guess that could be done in
xshmfence_alloc_shm().

> 
> Off the top of my head (sorry for the int32_t * argument type):

That seems a design flaw which could be easily rectified.  Should
defenitely be changed to 'void *', or perhaps an opaque 'struct
xshmfence *'.  Shouldn't affect the ABI.

> struct xshmfence {
>         pthread_mutex_t lock;
>         pthread_cond_t  wakeup;
>         int             value;
>         int             waiting;
> };
> 
> /**
>  * xshmfence_trigger:
>  * @f: An X fence
>  *
>  * Set @f to triggered, waking all waiters.
>  *
>  * Return value: 0 on success and -1 on error (in which case, errno
>  * will be set as appropriate).
>  **/
> int
> xshmfence_trigger(int32_t *v) {
>         struct xshmfence *f = (struct xshmfence *) v;
> 
>         pthread_mutex_lock(&f->lock);
>         if (f->value == 0) {
>                 f->value = 1;
>                 if (f->waiting) {
>                         f->waiting = 0;
>                         pthread_cond_broadcast(&f->wakeup);
>                 }
>         }
>         pthread_mutex_unlock(&f->lock);
>         return 0;
> }
> 
> /**
>  * xshmfence_await:
>  * @f: An X fence
>  *
>  * Wait for @f to be triggered. If @f is already triggered, this
>  * function returns immediately.
>  *
>  * Return value: 0 on success and -1 on error (in which case, errno
>  * will be set as appropriate).
>  **/
> int
> xshmfence_await(int32_t *v) {
>         struct xshmfence *f = (struct xshmfence *) v;
> 
>         pthread_mutex_lock(&f->lock);
>         if (f->value == 0) {
>                 f->waiting = 1;
>                 pthread_cond_wait(&f->wakeup, &f->lock);
>         }
>         pthread_mutex_unlock(&f->lock);
>         return 0;
> }
> 
> /**
>  * xshmfence_query:
>  * @f: An X fence
>  *
>  * Return value: 1 if @f is triggered, else returns 0.
>  **/
> int
> xshmfence_query(int32_t *v) {
>         struct xshmfence *f = (struct xshmfence *) v;
>         int value;
> 
>         pthread_mutex_lock(&v->lock);
>         value = f->value;
>         pthread_mutex_unlock(&v->lock);
>         return value;
> }
> 
> /**
>  * xshmfence_reset:
>  * @f: An X fence
>  *
>  * Reset @f to untriggered. If @f is already untriggered,
>  * this function has no effect.
>  **/
> void
> xshmfence_reset(int32_t *f) {
>         struct xshmfence *f = (struct xshmfence *) v;
> 
>         pthread_mutex_lock(&f->lock);
>         f->value = 0;
>         pthread_mutex_unlock(&f->lock);
> }
> 
> > Right now, xorg-server cannot build without xshmfence, and xshmfence cannot
> > build without Linux-only API's.   There needs to be some way for Solaris,
> > BSD, MacOS and Cygwin to build without this, whether it's making xshmfence
> > optional for xorg-server or making xshmfence work with mutexes or other
> > portable API's.
> 
> We can certainly disable DRI3 for platforms that don't have xshmfence
> available. I'm sorry I didn't do that when I added the DRI3 tests to the
> configure script.

Please do.  I fear the xserver is unbuildable for most of us now, also
because the MIT-XSHM protocol extensions are nowehere to be found.

Not sure what the xserver 1.15 release plan is, but I get the feeling
that you're trying to rush this in just before the release.  That
seems a seriously bad plan given the obvious lack of proper review and
testing that all this new stuff has received.  The issue raised by
Kristian defenitely feels like a show-stopper to me.  Perhaps you
should back everything out and try again after 1.15 has been released?


More information about the xorg-devel mailing list