mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
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.
This commit is contained in:
parent
f849f3ce2c
commit
40fa6e2023
2 changed files with 14 additions and 23 deletions
|
|
@ -47,7 +47,8 @@ class LIBPBD_API Semaphore {
|
||||||
sem_t* _sem;
|
sem_t* _sem;
|
||||||
sem_t* ptr_to_sem() const { return _sem; }
|
sem_t* ptr_to_sem() const { return _sem; }
|
||||||
#elif defined USE_FUTEX_SEMAPHORE
|
#elif defined USE_FUTEX_SEMAPHORE
|
||||||
std::atomic<unsigned int> _value;
|
int _futex;
|
||||||
|
std::atomic<int> _value;
|
||||||
#else
|
#else
|
||||||
mutable sem_t _sem;
|
mutable sem_t _sem;
|
||||||
sem_t* ptr_to_sem() const { return &_sem; }
|
sem_t* ptr_to_sem() const { return &_sem; }
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#ifdef USE_FUTEX_SEMAPHORE
|
#ifdef USE_FUTEX_SEMAPHORE
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/futex.h>
|
#include <linux/futex.h>
|
||||||
|
#include <sched.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -103,23 +104,19 @@ Semaphore::reset ()
|
||||||
int
|
int
|
||||||
Semaphore::signal ()
|
Semaphore::signal ()
|
||||||
{
|
{
|
||||||
std::atomic_fetch_add_explicit (&_value, 1, std::memory_order_release);
|
if (std::atomic_fetch_add_explicit (&_value, 1, std::memory_order_relaxed) < 0) {
|
||||||
return syscall (__NR_futex, &_value, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
|
while (syscall (__NR_futex, &_futex, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0) < 1) {
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Semaphore::wait ()
|
Semaphore::wait ()
|
||||||
{
|
{
|
||||||
unsigned int value = 1;
|
if (std::atomic_fetch_sub_explicit (&_value, 1, std::memory_order_relaxed) <= 0) {
|
||||||
while (!std::atomic_compare_exchange_weak_explicit (&_value, &value, value - 1, std::memory_order_acquire, std::memory_order_relaxed)) {
|
syscall(__NR_futex, &_futex, FUTEX_WAIT_PRIVATE, _futex, NULL, 0, 0);
|
||||||
if (value == 0) {
|
|
||||||
if (syscall (__NR_futex, &_value, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0)) {
|
|
||||||
if (errno != EAGAIN && errno != EINTR) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -127,16 +124,9 @@ Semaphore::wait ()
|
||||||
int
|
int
|
||||||
Semaphore::reset ()
|
Semaphore::reset ()
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int value = _value;
|
||||||
unsigned int value = 1;
|
_value = 0;
|
||||||
|
return value;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue