Ticket #8798: 0001-pthread_rwlock-use-a-mutex-for-process-private-locks.patch

File 0001-pthread_rwlock-use-a-mutex-for-process-private-locks.patch, 3.9 KB (added by korli, 7 years ago)

try 3

  • headers/posix/pthread.h

    From 81decf740770965e73d8bcb4c73d20115eb5beb1 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <jerome.duval@gmail.com>
    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 489aace..feaf8e3 100644
    a b extern "C" {  
    8080    { PTHREAD_MUTEX_RECURSIVE, 0, -42, -1, 0 }
    8181#define PTHREAD_COND_INITIALIZER    \
    8282    { 0, -42, NULL, 0, 0 }
     83#define PTHREAD_RWLOCK_INITIALIZER  \
     84    { 0, -1, {{0}} }
    8385
    8486/* mutex functions */
    8587extern int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • headers/posix/sys/types.h

    diff --git a/headers/posix/sys/types.h b/headers/posix/sys/types.h
    index b09aba5..64d497e 100644
    a b struct _pthread_rwlock {  
    105105    __haiku_std_int32   owner;
    106106    union {
    107107        struct {
    108             __haiku_std_int32   sem;
    109         } shared;
    110         struct {
    111             __haiku_std_int32   lock_sem;
    112             __haiku_std_int32   lock_count;
     108            __haiku_std_int32   mutex;
     109            __haiku_std_int32   unused;
    113110            __haiku_std_int32   reader_count;
    114111            __haiku_std_int32   writer_count;
    115112            void*               waiters[2];
    116113        } local;
     114        struct {
     115            __haiku_std_int32   sem;
     116        } shared;
    117117    } u;
    118118};
    119119
  • src/system/libroot/posix/pthread/pthread_rwlock.cpp

    diff --git a/src/system/libroot/posix/pthread/pthread_rwlock.cpp b/src/system/libroot/posix/pthread/pthread_rwlock.cpp
    index 65e83be..b2470ae 100644
    a b  
    1212#include <AutoLocker.h>
    1313#include <libroot_lock.h>
    1414#include <syscalls.h>
     15#include <user_mutex_defs.h>
    1516#include <user_thread.h>
    1617#include <util/DoublyLinkedList.h>
    1718
    1819#include "pthread_private.h"
    1920
    20 
    2121#define MAX_READER_COUNT    1000000
    2222
    2323#define RWLOCK_FLAG_SHARED  0x01
    struct SharedRWLock {  
    9393struct LocalRWLock {
    9494    uint32_t    flags;
    9595    int32_t     owner;
    96     int32_t     lock_sem;
    97     int32_t     lock_count;
     96    int32_t     mutex;
     97    int32_t     unused;
    9898    int32_t     reader_count;
    9999    int32_t     writer_count;
    100100        // Note, that reader_count and writer_count are not used the same way.
    struct LocalRWLock {  
    106106    {
    107107        flags = 0;
    108108        owner = -1;
    109         lock_sem = create_sem(0, "pthread rwlock");
    110         lock_count = 1;
     109        mutex = 0;
    111110        reader_count = 0;
    112111        writer_count = 0;
    113112        new(&waiters) WaiterList;
    114113
    115         return lock_sem >= 0 ? B_OK : EAGAIN;
     114        return B_OK;
    116115    }
    117116
    118117    status_t Destroy()
    119118    {
    120         if (lock_sem < 0)
    121             return B_BAD_VALUE;
    122         return delete_sem(lock_sem) == B_OK ? B_OK : B_BAD_VALUE;
     119        Locker locker(this);
     120        if (reader_count > 0 || waiters.Head() != NULL || writer_count > 0)
     121            return EBUSY;
     122        return B_OK;
    123123    }
    124124
    125125    bool StructureLock()
    126126    {
    127         if (atomic_add((int32*)&lock_count, -1) <= 0)
    128             acquire_sem(lock_sem);
     127        // Enter critical region: lock the mutex
     128        int32 status = atomic_or((int32*)&mutex, B_USER_MUTEX_LOCKED);
     129
     130        // If already locked, call the kernel
     131        if ((status & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) != 0) {
     132            do {
     133                status = _kern_mutex_lock((int32*)&mutex, NULL, 0, 0);
     134            } while (status == B_INTERRUPTED);
     135
     136            if (status != B_OK)
     137                return false;
     138        }
    129139        return true;
    130140    }
    131141
    132142    void StructureUnlock()
    133143    {
    134         if (atomic_add((int32*)&lock_count, 1) < 0)
    135             release_sem(lock_sem);
     144        // Exit critical region: unlock the mutex
     145        int32 status = atomic_and((int32*)&mutex,
     146            ~(int32)B_USER_MUTEX_LOCKED);
     147
     148        if ((status & B_USER_MUTEX_WAITING) != 0)
     149            _kern_mutex_unlock((int32*)&mutex, 0);
    136150    }
    137151
    138152    status_t ReadLock(bigtime_t timeout)