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:
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user