Implement Futex semaphore
This commit is contained in:
@@ -21,15 +21,19 @@
|
||||
#ifndef __pbd_semutils_h__
|
||||
#define __pbd_semutils_h__
|
||||
|
||||
#define USE_FUTEX_SEMAPHORE
|
||||
|
||||
#if (defined PLATFORM_WINDOWS && !defined USE_PTW32_SEMAPHORE)
|
||||
#define WINDOWS_SEMAPHORE 1
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS_SEMAPHORE
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
#elif defined USE_FUTEX_SEMAPHORE
|
||||
# include <atomic>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
# include <pthread.h>
|
||||
# include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#include "pbd/libpbd_visibility.h"
|
||||
@@ -44,6 +48,8 @@ class LIBPBD_API Semaphore {
|
||||
#elif __APPLE__
|
||||
sem_t* _sem;
|
||||
sem_t* ptr_to_sem() const { return _sem; }
|
||||
#elif defined USE_FUTEX_SEMAPHORE
|
||||
std::atomic<unsigned int> _value;
|
||||
#else
|
||||
mutable sem_t _sem;
|
||||
sem_t* ptr_to_sem() const { return &_sem; }
|
||||
@@ -53,7 +59,7 @@ class LIBPBD_API Semaphore {
|
||||
Semaphore (const char* name, int val);
|
||||
~Semaphore ();
|
||||
|
||||
#ifdef WINDOWS_SEMAPHORE
|
||||
#if defined WINDOWS_SEMAPHORE || defined USE_FUTEX_SEMAPHORE
|
||||
|
||||
int signal ();
|
||||
int wait ();
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
#include "pbd/semutils.h"
|
||||
#include "pbd/failed_constructor.h"
|
||||
|
||||
#ifdef USE_FUTEX_SEMAPHORE
|
||||
#include <errno.h>
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace PBD;
|
||||
|
||||
Semaphore::Semaphore (const char* name, int val)
|
||||
@@ -41,6 +48,9 @@ Semaphore::Semaphore (const char* name, int val)
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
#elif defined USE_FUTEX_SEMAPHORE
|
||||
(void)name; /* stop warning */
|
||||
_value = val;
|
||||
#else
|
||||
(void) name; /* stop gcc warning on !Apple systems */
|
||||
|
||||
@@ -88,4 +98,45 @@ Semaphore::reset ()
|
||||
return rv;
|
||||
}
|
||||
|
||||
#elif defined USE_FUTEX_SEMAPHORE
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user