|
|
@@ -19,13 +19,26 @@ |
|
|
|
|
|
|
|
#include <pthread.h> |
|
|
|
|
|
|
|
#ifdef __MOD_DEVICES__ |
|
|
|
#include <linux/futex.h> |
|
|
|
#include <sys/time.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <syscall.h> |
|
|
|
#include <unistd.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
/* replace Rack's mutex with our own custom one, which can do priority inversion. */ |
|
|
|
|
|
|
|
namespace rack { |
|
|
|
|
|
|
|
|
|
|
|
struct SharedMutex { |
|
|
|
pthread_mutex_t readLock, writeLock; |
|
|
|
pthread_mutex_t readLock; |
|
|
|
#ifdef __MOD_DEVICES__ |
|
|
|
int writeLock; |
|
|
|
#else |
|
|
|
pthread_mutex_t writeLock; |
|
|
|
#endif |
|
|
|
|
|
|
|
SharedMutex() noexcept { |
|
|
|
pthread_mutexattr_t attr; |
|
|
@@ -35,27 +48,52 @@ struct SharedMutex { |
|
|
|
pthread_mutex_init(&readLock, &attr); |
|
|
|
pthread_mutexattr_destroy(&attr); |
|
|
|
|
|
|
|
#ifdef __MOD_DEVICES__ |
|
|
|
writeLock = 1; |
|
|
|
#else |
|
|
|
pthread_mutexattr_t attr2; |
|
|
|
pthread_mutexattr_init(&attr2); |
|
|
|
pthread_mutexattr_setprotocol(&attr2, PTHREAD_PRIO_NONE); |
|
|
|
pthread_mutexattr_settype(&attr2, PTHREAD_MUTEX_NORMAL); |
|
|
|
pthread_mutex_init(&writeLock, &attr2); |
|
|
|
pthread_mutexattr_destroy(&attr2); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
~SharedMutex() noexcept { |
|
|
|
pthread_mutex_destroy(&readLock); |
|
|
|
#ifndef __MOD_DEVICES__ |
|
|
|
pthread_mutex_destroy(&writeLock); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// for std::lock_guard usage, writers lock |
|
|
|
void lock() noexcept { |
|
|
|
#ifdef __MOD_DEVICES__ |
|
|
|
for (;;) |
|
|
|
{ |
|
|
|
if (__sync_bool_compare_and_swap(&writeLock, 1, 0)) |
|
|
|
return; |
|
|
|
|
|
|
|
if (syscall(__NR_futex, &writeLock, FUTEX_WAIT_PRIVATE, 0, nullptr, nullptr, 0) != 0) |
|
|
|
{ |
|
|
|
if (errno != EAGAIN && errno != EINTR) |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
#else |
|
|
|
pthread_mutex_lock(&writeLock); |
|
|
|
#endif |
|
|
|
pthread_mutex_lock(&readLock); |
|
|
|
} |
|
|
|
void unlock() noexcept { |
|
|
|
pthread_mutex_unlock(&readLock); |
|
|
|
#ifdef __MOD_DEVICES__ |
|
|
|
if (__sync_bool_compare_and_swap(&writeLock, 0, 1)) |
|
|
|
syscall(__NR_futex, &writeLock, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0); |
|
|
|
#else |
|
|
|
pthread_mutex_unlock(&writeLock); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// for SharedLock usage, readers lock |
|
|
|