pthread_rwlock: use a mutex for process-private locks.

* instead of a benaphore.
* define PTHREAD_RWLOCK_INITIALIZER.
* adjust Init(), Destroy(), StructureLock() and StructureUnlock().
This commit is contained in:
Jérôme Duval
2017-07-27 18:33:53 +02:00
parent b34aa933ed
commit 6c9e01265b
3 changed files with 34 additions and 18 deletions
+2
View File
@@ -80,6 +80,8 @@ extern "C" {
{ PTHREAD_MUTEX_RECURSIVE, 0, -42, -1, 0 } { PTHREAD_MUTEX_RECURSIVE, 0, -42, -1, 0 }
#define PTHREAD_COND_INITIALIZER \ #define PTHREAD_COND_INITIALIZER \
{ 0, -42, NULL, 0, 0 } { 0, -42, NULL, 0, 0 }
#define PTHREAD_RWLOCK_INITIALIZER \
{ 0, -1, {{0}} }
/* mutex functions */ /* mutex functions */
extern int pthread_mutex_destroy(pthread_mutex_t *mutex); extern int pthread_mutex_destroy(pthread_mutex_t *mutex);
+5 -5
View File
@@ -105,15 +105,15 @@ struct _pthread_rwlock {
__haiku_std_int32 owner; __haiku_std_int32 owner;
union { union {
struct { struct {
__haiku_std_int32 sem; __haiku_std_int32 mutex;
} shared; __haiku_std_int32 unused;
struct {
__haiku_std_int32 lock_sem;
__haiku_std_int32 lock_count;
__haiku_std_int32 reader_count; __haiku_std_int32 reader_count;
__haiku_std_int32 writer_count; __haiku_std_int32 writer_count;
void* waiters[2]; void* waiters[2];
} local; } local;
struct {
__haiku_std_int32 sem;
} shared;
} u; } u;
}; };
@@ -12,12 +12,12 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include <libroot_lock.h> #include <libroot_lock.h>
#include <syscalls.h> #include <syscalls.h>
#include <user_mutex_defs.h>
#include <user_thread.h> #include <user_thread.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "pthread_private.h" #include "pthread_private.h"
#define MAX_READER_COUNT 1000000 #define MAX_READER_COUNT 1000000
#define RWLOCK_FLAG_SHARED 0x01 #define RWLOCK_FLAG_SHARED 0x01
@@ -93,8 +93,8 @@ struct SharedRWLock {
struct LocalRWLock { struct LocalRWLock {
uint32_t flags; uint32_t flags;
int32_t owner; int32_t owner;
int32_t lock_sem; int32_t mutex;
int32_t lock_count; int32_t unused;
int32_t reader_count; int32_t reader_count;
int32_t writer_count; int32_t writer_count;
// Note, that reader_count and writer_count are not used the same way. // Note, that reader_count and writer_count are not used the same way.
@@ -106,33 +106,47 @@ struct LocalRWLock {
{ {
flags = 0; flags = 0;
owner = -1; owner = -1;
lock_sem = create_sem(0, "pthread rwlock"); mutex = 0;
lock_count = 1;
reader_count = 0; reader_count = 0;
writer_count = 0; writer_count = 0;
new(&waiters) WaiterList; new(&waiters) WaiterList;
return lock_sem >= 0 ? B_OK : EAGAIN; return B_OK;
} }
status_t Destroy() status_t Destroy()
{ {
if (lock_sem < 0) Locker locker(this);
return B_BAD_VALUE; if (reader_count > 0 || waiters.Head() != NULL || writer_count > 0)
return delete_sem(lock_sem) == B_OK ? B_OK : B_BAD_VALUE; return EBUSY;
return B_OK;
} }
bool StructureLock() bool StructureLock()
{ {
if (atomic_add((int32*)&lock_count, -1) <= 0) // Enter critical region: lock the mutex
acquire_sem(lock_sem); 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; return true;
} }
void StructureUnlock() void StructureUnlock()
{ {
if (atomic_add((int32*)&lock_count, 1) < 0) // Exit critical region: unlock the mutex
release_sem(lock_sem); 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) status_t ReadLock(bigtime_t timeout)