From c904c1216f3a7767a5b59bdf1cb9460a97261adf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 20 Nov 2013 11:19:50 -0800 Subject: Split out futex implementation from general API This splits the futex-specific code out into a separate file so that future versions of the library could use some other underlying primitive. Signed-off-by: Keith Packard --- src/Makefile.am | 7 ++- src/xshmfence.c | 158 -------------------------------------------------- src/xshmfence_alloc.c | 88 ++++++++++++++++++++++++++++ src/xshmfence_futex.c | 94 ++++++++++++++++++++++++++++++ src/xshmfence_futex.h | 70 ++++++++++++++++++++++ src/xshmfenceint.h | 42 +------------- 6 files changed, 258 insertions(+), 201 deletions(-) delete mode 100644 src/xshmfence.c create mode 100644 src/xshmfence_alloc.c create mode 100644 src/xshmfence_futex.c create mode 100644 src/xshmfence_futex.h diff --git a/src/Makefile.am b/src/Makefile.am index 90d7bcb..d817326 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,12 @@ lib_LTLIBRARIES = libxshmfence.la +FUTEX_SOURCES=xshmfence_futex.c + libxshmfence_la_SOURCES = \ - xshmfence.c + xshmfence_alloc.c \ + $(FUTEX_SOURCES) -noinst_HEADERS = xshmfenceint.h +noinst_HEADERS = xshmfence_futex.h xshmfenceint.h libxshmfence_la_LDFLAGS = -version-number 1:0:0 -no-undefined diff --git a/src/xshmfence.c b/src/xshmfence.c deleted file mode 100644 index ed2b4c4..0000000 --- a/src/xshmfence.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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 "xshmfenceint.h" - -struct xshmfence { - int32_t v; -}; - -/** - * 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) -{ - if (__sync_val_compare_and_swap(&f->v, 0, 1) == -1) { - atomic_store(&f->v, 1); - if (futex_wake(&f->v) < 0) - return -1; - } - 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) -{ - while (__sync_val_compare_and_swap(&f->v, 0, -1) != 1) { - if (futex_wait(&f->v, -1)) { - if (errno != EWOULDBLOCK) - return -1; - } - } - return 0; -} - -/** - * xshmfence_query: - * @f: An X fence - * - * Return value: 1 if @f is triggered, else returns 0. - **/ -int -xshmfence_query(struct xshmfence *f) -{ - return atomic_fetch(&f->v) == 1; -} - -/** - * 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) -{ - __sync_bool_compare_and_swap(&f->v, 1, 0); -} - -/** - * xshmfence_alloc_shm: - * - * Allocates a shared memory object large enough to hold a single - * fence. - * - * Return value: the file descriptor of the object, or -1 on failure - * (in which case, errno will be set as appropriate). - **/ -int -xshmfence_alloc_shm(void) -{ - char template[] = SHMDIR "/shmfd-XXXXXX"; - int fd; - -#ifdef O_TMPFILE - fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); - if (fd < 0) -#endif - { - fd = mkstemp(template); - if (fd < 0) - return fd; - unlink(template); - } - ftruncate(fd, sizeof (struct xshmfence)); - return fd; -} - -/** - * xshmfence_map_shm: - * - * Map a shared memory fence referenced by @fd. - * - * Return value: the fence or NULL (in which case, errno will be set - * as appropriate). - **/ -struct xshmfence * -xshmfence_map_shm(int fd) -{ - struct xshmfence *addr; - addr = mmap (NULL, sizeof (struct xshmfence) , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (addr == MAP_FAILED) { - close (fd); - return 0; - } - return addr; -} - -/** - * xshmfence_unmap_shm: - * - * Unap a shared memory fence @f. - **/ -void -xshmfence_unmap_shm(struct xshmfence *f) -{ - munmap(f, sizeof (struct xshmfence)); -} diff --git a/src/xshmfence_alloc.c b/src/xshmfence_alloc.c new file mode 100644 index 0000000..d8d4a40 --- /dev/null +++ b/src/xshmfence_alloc.c @@ -0,0 +1,88 @@ +/* + * 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 "xshmfenceint.h" + +/** + * xshmfence_alloc_shm: + * + * Allocates a shared memory object large enough to hold a single + * fence. + * + * Return value: the file descriptor of the object, or -1 on failure + * (in which case, errno will be set as appropriate). + **/ +int +xshmfence_alloc_shm(void) +{ + char template[] = SHMDIR "/shmfd-XXXXXX"; + int fd; + +#ifdef O_TMPFILE + fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); + if (fd < 0) +#endif + { + fd = mkstemp(template); + if (fd < 0) + return fd; + unlink(template); + } + ftruncate(fd, sizeof (struct xshmfence)); + xshmfence_init(fd); + return fd; +} + +/** + * xshmfence_map_shm: + * + * Map a shared memory fence referenced by @fd. + * + * Return value: the fence or NULL (in which case, errno will be set + * as appropriate). + **/ +struct xshmfence * +xshmfence_map_shm(int fd) +{ + struct xshmfence *addr; + addr = mmap (NULL, sizeof (struct xshmfence) , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + close (fd); + return 0; + } + return addr; +} + +/** + * xshmfence_unmap_shm: + * + * Unap a shared memory fence @f. + **/ +void +xshmfence_unmap_shm(struct xshmfence *f) +{ + munmap(f, sizeof (struct xshmfence)); +} diff --git a/src/xshmfence_futex.c b/src/xshmfence_futex.c new file mode 100644 index 0000000..8b42491 --- /dev/null +++ b/src/xshmfence_futex.c @@ -0,0 +1,94 @@ +/* + * 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 "xshmfenceint.h" + +/** + * 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) +{ + if (__sync_val_compare_and_swap(&f->v, 0, 1) == -1) { + atomic_store(&f->v, 1); + if (futex_wake(&f->v) < 0) + return -1; + } + 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) +{ + while (__sync_val_compare_and_swap(&f->v, 0, -1) != 1) { + if (futex_wait(&f->v, -1)) { + if (errno != EWOULDBLOCK) + return -1; + } + } + return 0; +} + +/** + * xshmfence_query: + * @f: An X fence + * + * Return value: 1 if @f is triggered, else returns 0. + **/ +int +xshmfence_query(struct xshmfence *f) +{ + return atomic_fetch(&f->v) == 1; +} + +/** + * 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) +{ + __sync_bool_compare_and_swap(&f->v, 1, 0); +} diff --git a/src/xshmfence_futex.h b/src/xshmfence_futex.h new file mode 100644 index 0000000..ed60b6d --- /dev/null +++ b/src/xshmfence_futex.h @@ -0,0 +1,70 @@ +/* + * 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_FUTEX_H_ +#define _XSHMFENCE_FUTEX_H_ + +#include +#include +#include +#include +#include +#include + +static inline long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3) +{ + return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); +} + +static inline int futex_wake(int32_t *addr) { + return sys_futex(addr, FUTEX_WAKE, MAXINT, NULL, NULL, 0); +} + +static inline int futex_wait(int32_t *addr, int32_t value) { + return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0); +} + +#define barrier() __asm__ __volatile__("": : :"memory") + +static inline void atomic_store(int32_t *f, int32_t v) +{ + barrier(); + *f = v; + barrier(); +} + +static inline int32_t atomic_fetch(int32_t *a) +{ + int32_t v; + barrier(); + v = *a; + barrier(); + return v; +} + +struct xshmfence { + int32_t v; +}; + +#define xshmfence_init(fd) + +#endif /* _XSHMFENCE_FUTEX_H_ */ diff --git a/src/xshmfenceint.h b/src/xshmfenceint.h index 66862d0..3452a55 100644 --- a/src/xshmfenceint.h +++ b/src/xshmfenceint.h @@ -23,50 +23,10 @@ #ifndef _XSHMFENCEINT_H_ #define _XSHMFENCEINT_H_ -#include -#include -#include #include -#include -#include #include -#include #include -#include -#include -#include -#include #include "xshmfence.h" +#include "xshmfence_futex.h" -static inline long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3) -{ - return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); -} - -static inline int futex_wake(int32_t *addr) { - return sys_futex(addr, FUTEX_WAKE, MAXINT, NULL, NULL, 0); -} - -static inline int futex_wait(int32_t *addr, int32_t value) { - return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0); -} - -#define barrier() __asm__ __volatile__("": : :"memory") - -static inline void atomic_store(int32_t *f, int32_t v) -{ - barrier(); - *f = v; - barrier(); -} - -static inline int32_t atomic_fetch(int32_t *a) -{ - int32_t v; - barrier(); - v = *a; - barrier(); - return v; -} - #endif /* _XSHMFENCEINT_H_ */ -- cgit v1.2.3