diff options
author | tnn <tnn@pkgsrc.org> | 2015-09-24 23:34:16 +0000 |
---|---|---|
committer | tnn <tnn@pkgsrc.org> | 2015-09-24 23:34:16 +0000 |
commit | 1b09f247442e3673a275fd65cdccd524b4c11a46 (patch) | |
tree | 79ce2dcac4a2b08e5b00507003cc741ae70a7452 /x11 | |
parent | 49074949baf9dabd3bd2bfa14b409972364c5d0c (diff) | |
download | pkgsrc-1b09f247442e3673a275fd65cdccd524b4c11a46.tar.gz |
Add makeshift NetBSD support using POSIX semaphores.
Not upstreamed because I think NetBSD should be given the chance to
implement some better interprocess synchronization primitives first.
See PR lib/49529.
In particular what's missing is an interprocess sync primitive that can:
1) be passed safely through MAP_SHARED memory
2) support atomic unlock-and-block (like pthread_cond_wait)
3) wake up all waiters at once
Diffstat (limited to 'x11')
-rw-r--r-- | x11/libxshmfence/DESCR | 6 | ||||
-rw-r--r-- | x11/libxshmfence/Makefile | 23 | ||||
-rw-r--r-- | x11/libxshmfence/distinfo | 6 | ||||
-rw-r--r-- | x11/libxshmfence/files/xshmfence_semaphore.c | 217 | ||||
-rw-r--r-- | x11/libxshmfence/files/xshmfence_semaphore.h | 59 | ||||
-rw-r--r-- | x11/libxshmfence/patches/patch-configure.ac | 53 | ||||
-rw-r--r-- | x11/libxshmfence/patches/patch-src_Makefile.am | 23 | ||||
-rw-r--r-- | x11/libxshmfence/patches/patch-src_xshmfence__alloc.c | 23 | ||||
-rw-r--r-- | x11/libxshmfence/patches/patch-src_xshmfenceint.h | 15 |
9 files changed, 416 insertions, 9 deletions
diff --git a/x11/libxshmfence/DESCR b/x11/libxshmfence/DESCR index beb0029e337..8a84bf8fcc3 100644 --- a/x11/libxshmfence/DESCR +++ b/x11/libxshmfence/DESCR @@ -2,11 +2,13 @@ This library offers a CPU-based synchronization primitive compatible with the X SyncFence objects that can be shared between processes using file descriptor passing. -There are three underlying implementations: +There are four underlying implementations: 1) On Linux, the library uses futexes 2) On FreeBSD, the library uses umtx - 3) On other systems, the library uses posix mutexes and condition + 3) On NetBSD, the library uses POSIX semaphores (for now) + + 4) On other systems, the library uses posix mutexes and condition variables. diff --git a/x11/libxshmfence/Makefile b/x11/libxshmfence/Makefile index 5d8d0f3ca72..513f1ee0b7b 100644 --- a/x11/libxshmfence/Makefile +++ b/x11/libxshmfence/Makefile @@ -1,6 +1,7 @@ -# $NetBSD: Makefile,v 1.2 2015/09/16 18:38:34 jperkin Exp $ +# $NetBSD: Makefile,v 1.3 2015/09/24 23:34:16 tnn Exp $ DISTNAME= libxshmfence-1.2 +PKGREVISION= 1 CATEGORIES= x11 MASTER_SITES= http://xorg.freedesktop.org/archive/individual/lib/ EXTRACT_SUFX= .tar.bz2 @@ -12,15 +13,25 @@ LICENSE= mit GNU_CONFIGURE= yes USE_LIBTOOL= yes -USE_TOOLS+= pkg-config +USE_TOOLS+= pkg-config autoconf automake autoreconf PKGCONFIG_OVERRIDE+= xshmfence.pc.in -# Needs additional pthread functions or alternative synchronization -# implementation on NetBSD. See PR lib/49529. -# (On FreeBSD, umtx is used.) +.include "../../mk/bsd.prefs.mk" -ONLY_FOR_PLATFORM+= Linux-*-* FreeBSD-*-* SunOS-*-* +.if ${OPSYS} == "NetBSD" +CONFIGURE_ARGS+= --disable-futex +CONFIGURE_ARGS+= --enable-semaphore +LIBXSHM_PAGESIZE!= /sbin/sysctl -n hw.pagesize +CPPFLAGS+= -DLIBXSHM_PAGESIZE=${LIBXSHM_PAGESIZE} +.endif +post-extract: + cp ${FILESDIR}/xshmfence_semaphore.[ch] ${WRKSRC}/src + +pre-configure: + cd ${WRKSRC} && autoreconf -vif + +.include "../../devel/xorg-util-macros/buildlink3.mk" .include "../../x11/xproto/buildlink3.mk" .include "../../mk/bsd.pkg.mk" diff --git a/x11/libxshmfence/distinfo b/x11/libxshmfence/distinfo index 8c4bea7ccc9..00c5c2be272 100644 --- a/x11/libxshmfence/distinfo +++ b/x11/libxshmfence/distinfo @@ -1,5 +1,9 @@ -$NetBSD: distinfo,v 1.1 2015/04/29 14:31:42 tnn Exp $ +$NetBSD: distinfo,v 1.2 2015/09/24 23:34:16 tnn Exp $ SHA1 (libxshmfence-1.2.tar.bz2) = a2ebe90e5595afca4db93a4359732af43b2b8c69 RMD160 (libxshmfence-1.2.tar.bz2) = fe4b42d4ee01a993cd653d8f10334069bcc4791c Size (libxshmfence-1.2.tar.bz2) = 267170 bytes +SHA1 (patch-configure.ac) = 9301700c19d55b0c80f0265274ea6a158657d039 +SHA1 (patch-src_Makefile.am) = cdf80a7606cbc91ddca1443cd9210a3480de5241 +SHA1 (patch-src_xshmfence__alloc.c) = 355c20c55601c4ea71306d1e10cbd632b2d7f393 +SHA1 (patch-src_xshmfenceint.h) = 1996a0c18977c1e0f05fda3248ed3e97a181f6f1 diff --git a/x11/libxshmfence/files/xshmfence_semaphore.c b/x11/libxshmfence/files/xshmfence_semaphore.c new file mode 100644 index 00000000000..714d5b64399 --- /dev/null +++ b/x11/libxshmfence/files/xshmfence_semaphore.c @@ -0,0 +1,217 @@ +/* + * Copyright © 2015 Tobias Nygren + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <fcntl.h> +#include <string.h> +#include <err.h> +#include <unistd.h> + +#include "xshmfenceint.h" + +#define LOCK() do {} while (sem_wait(f->lock) != 0) +#define UNLOCK() do { sem_post(f->lock); } while (0) +#define COND_WAIT() do {} while (sem_wait(f->cond) != 0) +#define COND_SIGNAL() do { sem_post(f->cond); } while (0) + +/** + * 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(struct xshmfence *f) { + LOCK(); + int v = __sync_bool_compare_and_swap(&f->triggered, 0, 1); + if (v == 0) { + /* already triggered */ + UNLOCK(); + return 0; + } + + int waiting = __sync_fetch_and_add(&f->waiting, 0); + + while (waiting > 0) { + COND_SIGNAL(); + waiting--; + } + + while (__sync_fetch_and_add(&f->waiting, 0) > 0) { + /* + * Busy wait until they all woke up. + * No new sleepers should arrive since + * the lock is still held. + */ + /* yield(); */ + } + UNLOCK(); + 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(struct xshmfence *f) { + + LOCK(); + if (__sync_fetch_and_add(&f->triggered, 0) == 1) { + UNLOCK(); + return 0; + } + do { + __sync_fetch_and_add(&f->waiting, 1); + /* + * These next operations are not atomic. + * But we busy-wait in xshmfence_trigger, so that's ok. + */ + UNLOCK(); + COND_WAIT(); + __sync_fetch_and_sub(&f->waiting, 1); + LOCK(); + } + while (__sync_fetch_and_add(&f->triggered, 0) == 0); + UNLOCK(); + return 0; +} + +/** + * xshmfence_query: + * @f: An X fence + * + * Return value: 1 if @f is triggered, else returns 0. + **/ +int +xshmfence_query(struct xshmfence *f) { + int ret; + LOCK(); + ret = __sync_fetch_and_add(&f->triggered, 0); + UNLOCK(); + return ret; +} + +/** + * xshmfence_reset: + * @f: An X fence + * + * Reset @f to untriggered. If @f is already untriggered, + * this function has no effect. + **/ +void +xshmfence_reset(struct xshmfence *f) { + LOCK(); + __sync_bool_compare_and_swap(&f->triggered, 1, 0); + UNLOCK(); +} + +/** + * xshmfence_init: + * @fd: An fd for an X fence + * + * Initialize the fence when first allocated + **/ +void +xshmfence_init(int fd) +{ + sem_t *lock; + sem_t *cond; + struct xshmfence f; + + __sync_fetch_and_and(&f.triggered, 0); + __sync_fetch_and_and(&f.waiting, 0); + + strlcpy(f.lockname, "/xshmfl-XXXX", sizeof(f.lockname)); + mktemp(f.lockname); + lock = sem_open(f.lockname, O_CREAT|O_EXCL, 0600, 1); + if (lock == SEM_FAILED) { + err(EXIT_FAILURE, "xshmfence_init: sem_open"); + } + + strlcpy(f.condname, "/xshmfc-XXXX", sizeof(f.condname)); + mktemp(f.condname); + cond = sem_open(f.condname, O_CREAT|O_EXCL, 0600, 0); + if (cond == SEM_FAILED) { + err(EXIT_FAILURE, "xshmfence_init: sem_open"); + } + + sem_close(lock); + sem_close(cond); + + pwrite(fd, &f, sizeof(f), 0); +} + +/** + * xshmfence_open_semaphore: + * @f: An X fence + * + * Open the semaphore after mapping the fence + **/ +void +xshmfence_open_semaphore(struct xshmfence *f) +{ + /* + * map process local memory to page 2 + */ + if (mmap ((void*)&f->lock, + LIBXSHM_PAGESIZE, + PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_ANON, + -1, 0) == MAP_FAILED) { + errx(EXIT_FAILURE, "xshmfence_open_semaphore: mmap failed"); + } + + if ((f->lock = sem_open(f->lockname, 0 , 0)) == SEM_FAILED) { + errx(EXIT_FAILURE, "xshmfence_open_semaphore: sem_open failed"); + } + + if ((f->cond = sem_open(f->condname, 0 , 0)) == SEM_FAILED) { + errx(EXIT_FAILURE, "xshmfence_open_semaphore: sem_open failed"); + } +} + +/** + * xshmfence_close_semaphore: + * @f: An X fence + * + * Close the semaphore before unmapping the fence + **/ +void +xshmfence_close_semaphore(struct xshmfence *f) +{ + sem_close(f->lock); + sem_close(f->cond); +} diff --git a/x11/libxshmfence/files/xshmfence_semaphore.h b/x11/libxshmfence/files/xshmfence_semaphore.h new file mode 100644 index 00000000000..5b3df110044 --- /dev/null +++ b/x11/libxshmfence/files/xshmfence_semaphore.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2015 Tobias Nygren + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _XSHMFENCE_SEMAPHORE_H_ +#define _XSHMFENCE_SEMAPHORE_H_ + +#include <semaphore.h> + +#define LOCK_ALIGN __attribute__((aligned(128))) +#ifndef LIBXSHM_PAGESIZE +#error unknown machine page size +#endif +#define PAGE_ALIGN __attribute__((aligned(LIBXSHM_PAGESIZE))) + +/* + * the fence is divided into two memory pages: + * page 1 contains process shared state + * page 2 contains process local state + */ + +struct xshmfence { + /* page 1 */ + int triggered LOCK_ALIGN; + int waiting LOCK_ALIGN; + char lockname[16]; + char condname[16]; + /* page 2*/ + sem_t *lock PAGE_ALIGN; + sem_t *cond; +}; + +void +xshmfence_init(int fd); +void +xshmfence_open_semaphore(struct xshmfence *f); +void +xshmfence_close_semaphore(struct xshmfence *f); + +#endif /* _XSHMFENCE_SEMAPHORE_H_ */ diff --git a/x11/libxshmfence/patches/patch-configure.ac b/x11/libxshmfence/patches/patch-configure.ac new file mode 100644 index 00000000000..b1235f795ca --- /dev/null +++ b/x11/libxshmfence/patches/patch-configure.ac @@ -0,0 +1,53 @@ +$NetBSD: patch-configure.ac,v 1.1 2015/09/24 23:34:16 tnn Exp $ + +--- configure.ac.orig 2015-01-02 18:43:42.000000000 +0000 ++++ configure.ac +@@ -52,6 +52,9 @@ dnl + AC_ARG_ENABLE(futex, AS_HELP_STRING([--enable-futex], [Enable futexes (default: auto)]), + [FUTEX=$enableval], [FUTEX=auto]) + ++AC_ARG_ENABLE(semaphore, AS_HELP_STRING([--enable-semaphore], [Enable POSIX named semaphores (default: no)]), ++ [SEMAPHORE=$enableval], [FUTEX=no]) ++ + if test "x$FUTEX" = "xauto"; then + AC_CHECK_HEADER([linux/futex.h], [FUTEX=yes]) + fi +@@ -65,23 +68,36 @@ if test "x$FUTEX" = "xauto"; then + fi + fi + ++if test "x$SEMAPHORE" = "xyes"; then ++ AC_CHECK_HEADER([semaphore.h], [], [AC_MSG_ERROR([No platform support for POSIX named semaphores])]) ++fi ++ + if test "x$FUTEX" = "xyes"; then + PTHREAD=no + AC_DEFINE(HAVE_FUTEX,1,[Use futexes]) + else +- PTHREAD=yes +- AC_DEFINE(HAVE_PTHREAD,1,[Use pthread primitives]) ++ if test "x$SEMAPHORE" = "xyes"; then ++ PTHREAD=no ++ AC_DEFINE(HAVE_SEMAPHORE,1,[Use semaphores]) ++ else ++ PTHREAD=yes ++ AC_DEFINE(HAVE_PTHREAD,1,[Use pthread primitives]) ++ fi + fi + + PTHREAD_LIBS= + if test "x$PTHREAD" = "xyes"; then + AC_CHECK_LIB(pthread,pthread_create,[PTHREAD_LIBS=-lpthread],[PTHREAD_LIBS=]) + fi ++if test "x$SEMAPHORE" = "xyes"; then ++ AC_CHECK_LIB(rt,sem_open,[PTHREAD_LIBS=-lrt]) ++fi + + AC_SUBST([PTHREAD_LIBS]) + + AM_CONDITIONAL([FUTEX], [test x"$FUTEX" = xyes]) + AM_CONDITIONAL([PTHREAD], [test x"$PTHREAD" = xyes]) ++AM_CONDITIONAL([SEMAPHORE], [test x"$SEMAPHORE" = xyes]) + + PKG_CHECK_MODULES(XPROTO, xproto) + diff --git a/x11/libxshmfence/patches/patch-src_Makefile.am b/x11/libxshmfence/patches/patch-src_Makefile.am new file mode 100644 index 00000000000..6b8e1d62702 --- /dev/null +++ b/x11/libxshmfence/patches/patch-src_Makefile.am @@ -0,0 +1,23 @@ +$NetBSD: patch-src_Makefile.am,v 1.1 2015/09/24 23:34:16 tnn Exp $ + +--- src/Makefile.am.orig 2013-12-02 21:07:56.000000000 +0000 ++++ src/Makefile.am +@@ -4,6 +4,10 @@ if PTHREAD + PTHREAD_SOURCES=xshmfence_pthread.c xshmfence_pthread.h + endif + ++if SEMAPHORE ++SEMAPHORE_SOURCES=xshmfence_semaphore.c xshmfence_semaphore.h ++endif ++ + if FUTEX + FUTEX_SOURCES=xshmfence_futex.c xshmfence_futex.h + endif +@@ -12,6 +16,7 @@ libxshmfence_la_SOURCES = \ + xshmfenceint.h \ + xshmfence_alloc.c \ + $(PTHREAD_SOURCES) \ ++ $(SEMAPHORE_SOURCES) \ + $(FUTEX_SOURCES) + + AM_CFLAGS = $(CWARNFLAGS) diff --git a/x11/libxshmfence/patches/patch-src_xshmfence__alloc.c b/x11/libxshmfence/patches/patch-src_xshmfence__alloc.c new file mode 100644 index 00000000000..62553411e8c --- /dev/null +++ b/x11/libxshmfence/patches/patch-src_xshmfence__alloc.c @@ -0,0 +1,23 @@ +$NetBSD: patch-src_xshmfence__alloc.c,v 1.1 2015/09/24 23:34:16 tnn Exp $ + +--- src/xshmfence_alloc.c.orig 2014-10-09 12:09:03.000000000 +0000 ++++ src/xshmfence_alloc.c +@@ -110,6 +110,9 @@ xshmfence_map_shm(int fd) + close (fd); + return 0; + } ++#ifdef HAVE_SEMAPHORE ++ xshmfence_open_semaphore(addr); ++#endif + return addr; + } + +@@ -121,5 +124,8 @@ xshmfence_map_shm(int fd) + void + xshmfence_unmap_shm(struct xshmfence *f) + { ++#ifdef HAVE_SEMAPHORE ++ xshmfence_close_semaphore(f); ++#endif + munmap(f, sizeof (struct xshmfence)); + } diff --git a/x11/libxshmfence/patches/patch-src_xshmfenceint.h b/x11/libxshmfence/patches/patch-src_xshmfenceint.h new file mode 100644 index 00000000000..1ef00c85bfc --- /dev/null +++ b/x11/libxshmfence/patches/patch-src_xshmfenceint.h @@ -0,0 +1,15 @@ +$NetBSD: patch-src_xshmfenceint.h,v 1.1 2015/09/24 23:34:16 tnn Exp $ + +--- src/xshmfenceint.h.orig 2013-12-02 21:07:56.000000000 +0000 ++++ src/xshmfenceint.h +@@ -32,6 +32,10 @@ + #include "xshmfence_futex.h" + #endif + ++#if HAVE_SEMAPHORE ++#include "xshmfence_semaphore.h" ++#endif ++ + #if HAVE_PTHREAD + #include "xshmfence_pthread.h" + #endif |