diff options
author | tnn <tnn@pkgsrc.org> | 2020-02-23 22:47:47 +0000 |
---|---|---|
committer | tnn <tnn@pkgsrc.org> | 2020-02-23 22:47:47 +0000 |
commit | debabbd41339d206f91c8a66e94a97043d349397 (patch) | |
tree | d5890efd3604cadddd11ed67348f0f5533d491b3 | |
parent | 8329b49c6531721ae8939b9259286154564218b8 (diff) | |
download | pkgsrc-debabbd41339d206f91c8a66e94a97043d349397.tar.gz |
libxshmfence: improve performance of semaphore backend. Bump rev.
It used more locking that necessary. We only need two semaphores.
One to tell waiters to wake up and one to let the last waiter that
wakes up notify xshmfence_trigger() it may now return.
-rw-r--r-- | x11/libxshmfence/Makefile | 4 | ||||
-rw-r--r-- | x11/libxshmfence/files/xshmfence_semaphore.c | 98 | ||||
-rw-r--r-- | x11/libxshmfence/files/xshmfence_semaphore.h | 9 |
3 files changed, 46 insertions, 65 deletions
diff --git a/x11/libxshmfence/Makefile b/x11/libxshmfence/Makefile index 3444ade5842..33704935928 100644 --- a/x11/libxshmfence/Makefile +++ b/x11/libxshmfence/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.13 2020/01/18 23:35:54 rillig Exp $ +# $NetBSD: Makefile,v 1.14 2020/02/23 22:47:47 tnn Exp $ DISTNAME= libxshmfence-1.3 -PKGREVISION= 1 +PKGREVISION= 2 CATEGORIES= x11 MASTER_SITES= ${MASTER_SITE_XORG:=lib/} EXTRACT_SUFX= .tar.bz2 diff --git a/x11/libxshmfence/files/xshmfence_semaphore.c b/x11/libxshmfence/files/xshmfence_semaphore.c index a2d39aa3ac9..069338a1693 100644 --- a/x11/libxshmfence/files/xshmfence_semaphore.c +++ b/x11/libxshmfence/files/xshmfence_semaphore.c @@ -35,10 +35,10 @@ static sem_t *mksemtemp(char *, size_t, const char *); -#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) +#define COND_WAIT_W() do {} while (sem_wait(f->cond_w) != 0) +#define COND_SIGNAL_W() do { sem_post(f->cond_w); } while (0) +#define COND_WAIT_T() do {} while (sem_wait(f->cond_t) != 0) +#define COND_SIGNAL_T() do { sem_post(f->cond_t); } while (0) /** * xshmfence_trigger: @@ -52,30 +52,23 @@ static sem_t *mksemtemp(char *, size_t, const char *); int xshmfence_trigger(struct xshmfence *f) { int v, waiting; - LOCK(); v = __sync_bool_compare_and_swap(&f->triggered, 0, 1); if (v == 0) { /* already triggered */ - UNLOCK(); return 0; } - - waiting = __sync_fetch_and_add(&f->waiting, 0); - while (waiting > 0) { - COND_SIGNAL(); - waiting--; + while ((waiting = __sync_fetch_and_add(&f->waiting, 0)) > 0) { + if (__sync_bool_compare_and_swap(&f->waiting, waiting, 0)) { + __sync_fetch_and_add(&f->wakeups, waiting); + while (waiting--) { + COND_SIGNAL_W(); + } + COND_WAIT_T(); + return 0; + } } - 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; } @@ -92,24 +85,18 @@ xshmfence_trigger(struct xshmfence *f) { 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(); + COND_WAIT_W(); + } while (__sync_fetch_and_add(&f->triggered, 0) == 0); + + if (__sync_sub_and_fetch(&f->wakeups, 1) == 0) { + COND_SIGNAL_T(); } - while (__sync_fetch_and_add(&f->triggered, 0) == 0); - UNLOCK(); + return 0; } @@ -121,11 +108,7 @@ xshmfence_await(struct xshmfence *f) { **/ int xshmfence_query(struct xshmfence *f) { - int ret; - LOCK(); - ret = __sync_fetch_and_add(&f->triggered, 0); - UNLOCK(); - return ret; + return __sync_fetch_and_add(&f->triggered, 0); } /** @@ -137,9 +120,7 @@ xshmfence_query(struct xshmfence *f) { **/ void xshmfence_reset(struct xshmfence *f) { - LOCK(); __sync_bool_compare_and_swap(&f->triggered, 1, 0); - UNLOCK(); } /** @@ -151,27 +132,26 @@ xshmfence_reset(struct xshmfence *f) { void xshmfence_init(int fd) { - sem_t *lock; - sem_t *cond; + sem_t *cond_w, *cond_t; struct xshmfence f; __sync_fetch_and_and(&f.refcnt, 0); __sync_fetch_and_and(&f.triggered, 0); __sync_fetch_and_and(&f.waiting, 0); - - lock = mksemtemp(f.lockname, sizeof(f.lockname), "l"); - if (lock == SEM_FAILED) { + __sync_fetch_and_and(&f.wakeups, 0); + + cond_w = mksemtemp(f.condname_w, sizeof(f.condname_w), "w"); + if (cond_w == SEM_FAILED) { err(EXIT_FAILURE, "xshmfence_init: sem_open"); } - - cond = mksemtemp(f.condname, sizeof(f.condname), "c"); - if (cond == SEM_FAILED) { + cond_t = mksemtemp(f.condname_t, sizeof(f.condname_t), "t"); + if (cond_t == SEM_FAILED) { err(EXIT_FAILURE, "xshmfence_init: sem_open"); } - - sem_close(lock); - sem_close(cond); - + + sem_close(cond_w); + sem_close(cond_t); + pwrite(fd, &f, sizeof(f), 0); } @@ -187,7 +167,7 @@ xshmfence_open_semaphore(struct xshmfence *f) /* * map process local memory to page 2 */ - if (mmap ((void*)&f->lock, + if (mmap ((void*)&f->cond_w, LIBXSHM_PAGESIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANON, @@ -195,11 +175,11 @@ xshmfence_open_semaphore(struct xshmfence *f) errx(EXIT_FAILURE, "xshmfence_open_semaphore: mmap failed"); } - if ((f->lock = sem_open(f->lockname, 0 , 0)) == SEM_FAILED) { + if ((f->cond_w = sem_open(f->condname_w, 0)) == SEM_FAILED) { errx(EXIT_FAILURE, "xshmfence_open_semaphore: sem_open failed"); } - if ((f->cond = sem_open(f->condname, 0 , 0)) == SEM_FAILED) { + if ((f->cond_t = sem_open(f->condname_t, 0)) == SEM_FAILED) { errx(EXIT_FAILURE, "xshmfence_open_semaphore: sem_open failed"); } __sync_fetch_and_add(&f->refcnt, 1); @@ -214,11 +194,11 @@ xshmfence_open_semaphore(struct xshmfence *f) void xshmfence_close_semaphore(struct xshmfence *f) { - sem_close(f->lock); - sem_close(f->cond); + sem_close(f->cond_w); + sem_close(f->cond_t); if (__sync_sub_and_fetch(&f->refcnt, 1) == 0) { - sem_unlink(f->lockname); - sem_unlink(f->condname); + sem_unlink(f->condname_w); + sem_unlink(f->condname_t); } } @@ -231,7 +211,7 @@ mksemtemp(char *name, size_t namelen, const char *suffix) for(;;) { if (snprintf(name, namelen, "/xshmf%s-%d", suffix, p) >= namelen) return SEM_FAILED; - ret = sem_open(name, O_CREAT|O_EXCL, 0600, 1); + ret = sem_open(name, O_CREAT|O_EXCL, 0600, 0); if (ret == SEM_FAILED) { if (errno == EEXIST) { p++; diff --git a/x11/libxshmfence/files/xshmfence_semaphore.h b/x11/libxshmfence/files/xshmfence_semaphore.h index 1631e6bf2e3..3331d0a1416 100644 --- a/x11/libxshmfence/files/xshmfence_semaphore.h +++ b/x11/libxshmfence/files/xshmfence_semaphore.h @@ -43,11 +43,12 @@ struct xshmfence { int refcnt LOCK_ALIGN; int triggered LOCK_ALIGN; int waiting LOCK_ALIGN; - char lockname[16]; - char condname[16]; + int wakeups LOCK_ALIGN; + char condname_w[16]; + char condname_t[16]; /* page 2*/ - sem_t *lock PAGE_ALIGN; - sem_t *cond; + sem_t *cond_w PAGE_ALIGN; + sem_t *cond_t; }; void |