From 6c9e01265b8fe7f392ee55ff51b3bdc1c09b5b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 24 Jul 2017 21:09:55 +0200 Subject: [PATCH] pthread_rwlock: use a mutex for process-private locks. * instead of a benaphore. * define PTHREAD_RWLOCK_INITIALIZER. * adjust Init(), Destroy(), StructureLock() and StructureUnlock(). --- headers/posix/pthread.h | 2 + headers/posix/sys/types.h | 10 ++--- .../libroot/posix/pthread/pthread_rwlock.cpp | 40 +++++++++++++------ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/headers/posix/pthread.h b/headers/posix/pthread.h index 489aace5ba..feaf8e340b 100644 --- a/headers/posix/pthread.h +++ b/headers/posix/pthread.h @@ -80,6 +80,8 @@ extern "C" { { PTHREAD_MUTEX_RECURSIVE, 0, -42, -1, 0 } #define PTHREAD_COND_INITIALIZER \ { 0, -42, NULL, 0, 0 } +#define PTHREAD_RWLOCK_INITIALIZER \ + { 0, -1, {{0}} } /* mutex functions */ extern int pthread_mutex_destroy(pthread_mutex_t *mutex); diff --git a/headers/posix/sys/types.h b/headers/posix/sys/types.h index b09aba569a..64d497eba9 100644 --- a/headers/posix/sys/types.h +++ b/headers/posix/sys/types.h @@ -105,15 +105,15 @@ struct _pthread_rwlock { __haiku_std_int32 owner; union { struct { - __haiku_std_int32 sem; - } shared; - struct { - __haiku_std_int32 lock_sem; - __haiku_std_int32 lock_count; + __haiku_std_int32 mutex; + __haiku_std_int32 unused; __haiku_std_int32 reader_count; __haiku_std_int32 writer_count; void* waiters[2]; } local; + struct { + __haiku_std_int32 sem; + } shared; } u; }; diff --git a/src/system/libroot/posix/pthread/pthread_rwlock.cpp b/src/system/libroot/posix/pthread/pthread_rwlock.cpp index 65e83bed37..b2470aea08 100644 --- a/src/system/libroot/posix/pthread/pthread_rwlock.cpp +++ b/src/system/libroot/posix/pthread/pthread_rwlock.cpp @@ -12,12 +12,12 @@ #include #include #include +#include #include #include #include "pthread_private.h" - #define MAX_READER_COUNT 1000000 #define RWLOCK_FLAG_SHARED 0x01 @@ -93,8 +93,8 @@ struct SharedRWLock { struct LocalRWLock { uint32_t flags; int32_t owner; - int32_t lock_sem; - int32_t lock_count; + int32_t mutex; + int32_t unused; int32_t reader_count; int32_t writer_count; // Note, that reader_count and writer_count are not used the same way. @@ -106,33 +106,47 @@ struct LocalRWLock { { flags = 0; owner = -1; - lock_sem = create_sem(0, "pthread rwlock"); - lock_count = 1; + mutex = 0; reader_count = 0; writer_count = 0; new(&waiters) WaiterList; - return lock_sem >= 0 ? B_OK : EAGAIN; + return B_OK; } status_t Destroy() { - if (lock_sem < 0) - return B_BAD_VALUE; - return delete_sem(lock_sem) == B_OK ? B_OK : B_BAD_VALUE; + Locker locker(this); + if (reader_count > 0 || waiters.Head() != NULL || writer_count > 0) + return EBUSY; + return B_OK; } bool StructureLock() { - if (atomic_add((int32*)&lock_count, -1) <= 0) - acquire_sem(lock_sem); + // Enter critical region: lock the mutex + int32 status = atomic_or((int32*)&mutex, B_USER_MUTEX_LOCKED); + + // If already locked, call the kernel + if ((status & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) != 0) { + do { + status = _kern_mutex_lock((int32*)&mutex, NULL, 0, 0); + } while (status == B_INTERRUPTED); + + if (status != B_OK) + return false; + } return true; } void StructureUnlock() { - if (atomic_add((int32*)&lock_count, 1) < 0) - release_sem(lock_sem); + // Exit critical region: unlock the mutex + int32 status = atomic_and((int32*)&mutex, + ~(int32)B_USER_MUTEX_LOCKED); + + if ((status & B_USER_MUTEX_WAITING) != 0) + _kern_mutex_unlock((int32*)&mutex, 0); } status_t ReadLock(bigtime_t timeout)