From 40fa6e2023626c750ba8d87b41e5d0f0e3f43ce7 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 12 May 2022 04:49:11 +0200 Subject: [PATCH] Improve PBD::Semaphore performance Skip syscall if no threads are waiting and decouple atomic value from futex address so that FUTEX_WAIT does not fail. --- libs/pbd/pbd/semutils.h | 3 ++- libs/pbd/semutils.cc | 34 ++++++++++++---------------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/libs/pbd/pbd/semutils.h b/libs/pbd/pbd/semutils.h index b1b6bf41f4..bdc47072d2 100644 --- a/libs/pbd/pbd/semutils.h +++ b/libs/pbd/pbd/semutils.h @@ -47,7 +47,8 @@ class LIBPBD_API Semaphore { sem_t* _sem; sem_t* ptr_to_sem() const { return _sem; } #elif defined USE_FUTEX_SEMAPHORE - std::atomic _value; + int _futex; + std::atomic _value; #else mutable sem_t _sem; sem_t* ptr_to_sem() const { return &_sem; } diff --git a/libs/pbd/semutils.cc b/libs/pbd/semutils.cc index ba7b4e2bcb..0d8c603aa2 100644 --- a/libs/pbd/semutils.cc +++ b/libs/pbd/semutils.cc @@ -23,6 +23,7 @@ #ifdef USE_FUTEX_SEMAPHORE #include #include +#include #include #include #endif @@ -103,23 +104,19 @@ Semaphore::reset () int Semaphore::signal () { - std::atomic_fetch_add_explicit (&_value, 1, std::memory_order_release); - return syscall (__NR_futex, &_value, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); + if (std::atomic_fetch_add_explicit (&_value, 1, std::memory_order_relaxed) < 0) { + while (syscall (__NR_futex, &_futex, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0) < 1) { + sched_yield(); + } + } + return 0; } int Semaphore::wait () { - unsigned int value = 1; - while (!std::atomic_compare_exchange_weak_explicit (&_value, &value, value - 1, std::memory_order_acquire, std::memory_order_relaxed)) { - if (value == 0) { - if (syscall (__NR_futex, &_value, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0)) { - if (errno != EAGAIN && errno != EINTR) { - return 1; - } - } - value = 1; - } + if (std::atomic_fetch_sub_explicit (&_value, 1, std::memory_order_relaxed) <= 0) { + syscall(__NR_futex, &_futex, FUTEX_WAIT_PRIVATE, _futex, NULL, 0, 0); } return 0; } @@ -127,16 +124,9 @@ Semaphore::wait () int Semaphore::reset () { - int rv = 0; - unsigned int value = 1; - - while (!std::atomic_compare_exchange_weak_explicit (&_value, &value, value - 1, std::memory_order_acquire, std::memory_order_relaxed)) { - if (value == 0) { - break; - } - ++rv; - } - return rv; + int value = _value; + _value = 0; + return value; } #endif