[haiku-commits] r34364 - in haiku/trunk: headers/private/shared src/system/libroot/os src/system/libroot/os/locks src/system/runtime_loader src/system/runtime_loader/arch/m68k ...

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 30 Nov 2009 11:29:51 +0100 (CET)

Author: bonefish
Date: 2009-11-30 11:29:51 +0100 (Mon, 30 Nov 2009)
New Revision: 34364
Changeset: http://dev.haiku-os.org/changeset/34364/haiku

Added:
   haiku/trunk/src/system/libroot/os/locks/
   haiku/trunk/src/system/libroot/os/locks/mutex.cpp
   haiku/trunk/src/system/libroot/os/locks/recursive_lock.cpp
   haiku/trunk/src/system/libroot/os/locks/rw_lock.cpp
Removed:
   haiku/trunk/src/system/libroot/os/locks.cpp
Modified:
   haiku/trunk/headers/private/shared/locks.h
   haiku/trunk/src/system/libroot/os/Jamfile
   haiku/trunk/src/system/runtime_loader/Jamfile
   haiku/trunk/src/system/runtime_loader/arch/m68k/Jamfile
   haiku/trunk/src/system/runtime_loader/arch/ppc/Jamfile
   haiku/trunk/src/system/runtime_loader/arch/x86/Jamfile
Log:
* Fixed wrong parameter of lazy_mutex_destroy().
* Split locks.cpp into mutex.cpp, recursive_lock.cpp, and rw_lock.cpp (new
  subdirectory locks/).
* runtime_loader no longer includes the rw_lock, allowing removal of the TLS
  dependency again.


Modified: haiku/trunk/headers/private/shared/locks.h
===================================================================
--- haiku/trunk/headers/private/shared/locks.h  2009-11-30 08:31:31 UTC (rev 
34363)
+++ haiku/trunk/headers/private/shared/locks.h  2009-11-30 10:29:51 UTC (rev 
34364)
@@ -30,7 +30,7 @@
 
 status_t       lazy_mutex_init(lazy_mutex *lock, const char *name);
                                // name will not be cloned and must rename valid
-void           lazy_mutex_destroy(mutex *lock);
+void           lazy_mutex_destroy(lazy_mutex *lock);
 status_t       lazy_mutex_lock(lazy_mutex *lock);
 void           lazy_mutex_unlock(lazy_mutex *lock);
 

Modified: haiku/trunk/src/system/libroot/os/Jamfile
===================================================================
--- haiku/trunk/src/system/libroot/os/Jamfile   2009-11-30 08:31:31 UTC (rev 
34363)
+++ haiku/trunk/src/system/libroot/os/Jamfile   2009-11-30 10:29:51 UTC (rev 
34364)
@@ -5,6 +5,8 @@
        # for util/KMessage.h
 UsePrivateHeaders libroot runtime_loader shared ;
 
+SEARCH_SOURCE += [ FDirName $(SUBDIR) locks ] ;
+
 MergeObject os_main.o :
        area.c
        atomic.c
@@ -17,7 +19,6 @@
        fs_query.cpp
        fs_volume.c
        image.cpp
-       locks.cpp
        parsedate.cpp
        port.c
        scheduler.c
@@ -29,6 +30,11 @@
        syscalls.S
        wait_for_objects.cpp
 
+       # locks
+       mutex.cpp
+       recursive_lock.cpp
+       rw_lock.cpp
+
        KMessage.cpp
 ;
 

Copied: haiku/trunk/src/system/libroot/os/locks/mutex.cpp (from rev 34363, 
haiku/trunk/src/system/libroot/os/locks.cpp)
===================================================================
--- haiku/trunk/src/system/libroot/os/locks/mutex.cpp                           
(rev 0)
+++ haiku/trunk/src/system/libroot/os/locks/mutex.cpp   2009-11-30 10:29:51 UTC 
(rev 34364)
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2009, Michael Lotz, mmlr@xxxxxxxxx
+ * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights 
reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
+ * Distributed under the terms of the NewOS License.
+ */
+
+
+#include <locks.h>
+
+#include <OS.h>
+
+
+// #pragma mark - mutex
+
+
+status_t
+mutex_init(mutex *lock, const char *name)
+{
+       if (lock == NULL || name == NULL)
+               return B_BAD_VALUE;
+
+       lock->benaphore = 0;
+       lock->semaphore = create_sem(0, name);
+       if (lock->semaphore < 0)
+               return lock->semaphore;
+
+       return B_OK;
+}
+
+
+void
+mutex_destroy(mutex *lock)
+{
+       delete_sem(lock->semaphore);
+}
+
+
+status_t
+mutex_lock(mutex *lock)
+{
+       if (atomic_add(&lock->benaphore, 1) == 0)
+               return B_OK;
+
+       status_t result;
+       do {
+               result = acquire_sem(lock->semaphore);
+       } while (result == B_INTERRUPTED);
+
+       return result;
+}
+
+
+void
+mutex_unlock(mutex *lock)
+{
+       if (atomic_add(&lock->benaphore, -1) != 1)
+               release_sem(lock->semaphore);
+}
+
+
+// #pragma mark - lazy mutex
+
+
+enum {
+       STATE_UNINITIALIZED     = -1,
+       STATE_INITIALIZING      = -2,
+       STATE_SPIN_LOCKED       = -3,
+       STATE_SPIN_UNLOCKED     = -4
+};
+
+
+static inline bool
+lazy_mutex_ensure_init(lazy_mutex *lock)
+{
+       int32 value = atomic_test_and_set((vint32*)&lock->semaphore,
+               STATE_INITIALIZING, STATE_UNINITIALIZED);
+
+       if (value >= 0)
+               return true;
+
+       if (value == STATE_UNINITIALIZED) {
+               // we're the first -- perform the initialization
+               sem_id semaphore = create_sem(0, lock->name);
+               if (semaphore < 0)
+                       semaphore = STATE_SPIN_UNLOCKED;
+               atomic_set((vint32*)&lock->semaphore, semaphore);
+               return semaphore >= 0;
+       }
+
+       if (value == STATE_INITIALIZING) {
+               // someone else is initializing -- spin until that is done
+               while (atomic_get((vint32*)&lock->semaphore) == 
STATE_INITIALIZING) {
+               }
+       }
+
+       return lock->semaphore >= 0;
+}
+
+
+status_t
+lazy_mutex_init(lazy_mutex *lock, const char *name)
+{
+       if (lock == NULL || name == NULL)
+               return B_BAD_VALUE;
+
+       lock->benaphore = 0;
+       lock->semaphore = STATE_UNINITIALIZED;
+       lock->name = name;
+
+       return B_OK;
+}
+
+
+void
+lazy_mutex_destroy(lazy_mutex *lock)
+{
+       if (lock->semaphore >= 0)
+               delete_sem(lock->semaphore);
+}
+
+
+status_t
+lazy_mutex_lock(lazy_mutex *lock)
+{
+       if (atomic_add(&lock->benaphore, 1) == 0)
+               return B_OK;
+
+       if (lazy_mutex_ensure_init(lock)) {
+               // acquire the semaphore
+               status_t result;
+               do {
+                       result = acquire_sem(lock->semaphore);
+               } while (result == B_INTERRUPTED);
+
+               return result;
+       } else {
+               // the semaphore creation failed -- so we use it like a 
spinlock instead
+               while (atomic_test_and_set((vint32*)&lock->semaphore,
+                               STATE_SPIN_LOCKED, STATE_SPIN_UNLOCKED)
+                                       != STATE_SPIN_UNLOCKED) {
+               }
+               return B_OK;
+       }
+}
+
+
+void
+lazy_mutex_unlock(lazy_mutex *lock)
+{
+       if (atomic_add(&lock->benaphore, -1) == 1)
+               return;
+
+       if (lazy_mutex_ensure_init(lock)) {
+               // release the semaphore
+               release_sem(lock->semaphore);
+       } else {
+               // the semaphore creation failed -- so we use it like a 
spinlock instead
+               atomic_set((vint32*)&lock->semaphore, STATE_SPIN_UNLOCKED);
+       }
+}

Copied: haiku/trunk/src/system/libroot/os/locks/recursive_lock.cpp (from rev 
34363, haiku/trunk/src/system/libroot/os/locks.cpp)
===================================================================
--- haiku/trunk/src/system/libroot/os/locks/recursive_lock.cpp                  
        (rev 0)
+++ haiku/trunk/src/system/libroot/os/locks/recursive_lock.cpp  2009-11-30 
10:29:51 UTC (rev 34364)
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2009, Michael Lotz, mmlr@xxxxxxxxx
+ * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights 
reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
+ * Distributed under the terms of the NewOS License.
+ */
+
+
+#include <locks.h>
+
+#include <OS.h>
+
+
+// #pragma mark - recursive lock
+
+
+int32
+recursive_lock_get_recursion(recursive_lock *lock)
+{
+       if (lock->holder == find_thread(NULL))
+               return lock->recursion;
+
+       return -1;
+}
+
+
+status_t
+recursive_lock_init(recursive_lock *lock, const char *name)
+{
+       lock->holder = -1;
+       lock->recursion = 0;
+       return mutex_init(&lock->lock, name != NULL ? name : "recursive lock");
+}
+
+
+void
+recursive_lock_destroy(recursive_lock *lock)
+{
+       if (lock == NULL)
+               return;
+
+       mutex_destroy(&lock->lock);
+}
+
+
+status_t
+recursive_lock_lock(recursive_lock *lock)
+{
+       thread_id thread = find_thread(NULL);
+
+       if (thread != lock->holder) {
+               mutex_lock(&lock->lock);
+               lock->holder = thread;
+       }
+
+       lock->recursion++;
+       return B_OK;
+}
+
+
+void
+recursive_lock_unlock(recursive_lock *lock)
+{
+       if (find_thread(NULL) != lock->holder) {
+               debugger("recursive_lock unlocked by non-holder thread!\n");
+               return;
+       }
+
+       if (--lock->recursion == 0) {
+               lock->holder = -1;
+               mutex_unlock(&lock->lock);
+       }
+}
+
+
+// #pragma mark - lazy recursive lock
+
+
+int32
+lazy_recursive_lock_get_recursion(lazy_recursive_lock *lock)
+{
+       if (lock->holder == find_thread(NULL))
+               return lock->recursion;
+
+       return -1;
+}
+
+
+status_t
+lazy_recursive_lock_init(lazy_recursive_lock *lock, const char *name)
+{
+       lock->holder = -1;
+       lock->recursion = 0;
+       return lazy_mutex_init(&lock->lock, name != NULL ? name : "recursive 
lock");
+}
+
+
+void
+lazy_recursive_lock_destroy(lazy_recursive_lock *lock)
+{
+       if (lock == NULL)
+               return;
+
+       lazy_mutex_destroy(&lock->lock);
+}
+
+
+status_t
+lazy_recursive_lock_lock(lazy_recursive_lock *lock)
+{
+       thread_id thread = find_thread(NULL);
+
+       if (thread != lock->holder) {
+               lazy_mutex_lock(&lock->lock);
+               lock->holder = thread;
+       }
+
+       lock->recursion++;
+       return B_OK;
+}
+
+
+void
+lazy_recursive_lock_unlock(lazy_recursive_lock *lock)
+{
+       if (find_thread(NULL) != lock->holder) {
+               debugger("lazy_recursive_lock unlocked by non-holder 
thread!\n");
+               return;
+       }
+
+       if (--lock->recursion == 0) {
+               lock->holder = -1;
+               lazy_mutex_unlock(&lock->lock);
+       }
+}

Copied: haiku/trunk/src/system/libroot/os/locks/rw_lock.cpp (from rev 34363, 
haiku/trunk/src/system/libroot/os/locks.cpp)
===================================================================
--- haiku/trunk/src/system/libroot/os/locks/rw_lock.cpp                         
(rev 0)
+++ haiku/trunk/src/system/libroot/os/locks/rw_lock.cpp 2009-11-30 10:29:51 UTC 
(rev 34364)
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2009, Michael Lotz, mmlr@xxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <locks.h>
+
+#include <OS.h>
+
+#include <syscalls.h>
+#include <user_thread.h>
+
+
+typedef struct rw_lock_waiter {
+       rw_lock_waiter *        next;
+       thread_id                       thread;
+       bool                            writer;
+} rw_lock_waiter;
+
+
+static status_t
+rw_lock_wait(rw_lock *lock, bool writer)
+{
+       rw_lock_waiter waiter;
+       waiter.thread = find_thread(NULL);
+       waiter.next = NULL;
+       waiter.writer = writer;
+
+       if (lock->waiters != NULL)
+               lock->last_waiter->next = &waiter;
+       else
+               lock->waiters = &waiter;
+
+       lock->last_waiter = &waiter;
+
+       // the rw_lock is locked when entering, release it before blocking
+       get_user_thread()->wait_status = 1;
+       mutex_unlock(&lock->lock);
+
+       status_t result;
+       do {
+               result = _kern_block_thread(0, 0);
+       } while (result == B_INTERRUPTED);
+
+       // and lock it again before returning
+       mutex_lock(&lock->lock);
+       return result;
+}
+
+
+static void
+rw_lock_unblock(rw_lock *lock)
+{
+       // this is called locked
+       if (lock->holder >= 0)
+               return;
+
+       rw_lock_waiter *waiter = lock->waiters;
+       if (waiter == NULL)
+               return;
+
+       if (waiter->writer) {
+               if (lock->reader_count > 0)
+                       return;
+
+               lock->waiters = waiter->next;
+               lock->holder = waiter->thread;
+               _kern_unblock_thread(waiter->thread, B_OK);
+               return;
+       }
+
+       while (waiter != NULL && !waiter->writer) {
+               lock->reader_count++;
+               lock->waiters = waiter->next;
+               _kern_unblock_thread(waiter->thread, B_OK);
+               waiter = lock->waiters;
+       }
+}
+
+
+status_t
+rw_lock_init(rw_lock *lock, const char *name)
+{
+       lock->name = name;
+       lock->waiters = NULL;
+       lock->holder = -1;
+       lock->reader_count = 0;
+       lock->writer_count = 0;
+       lock->owner_count = 0;
+       return mutex_init(&lock->lock, name);
+}
+
+
+void
+rw_lock_destroy(rw_lock *lock)
+{
+       mutex_lock(&lock->lock);
+
+       rw_lock_waiter *waiter = lock->waiters;
+       while (waiter != NULL) {
+               _kern_unblock_thread(waiter->thread, B_ERROR);
+               waiter = waiter->next;
+       }
+
+       mutex_destroy(&lock->lock);
+}
+
+
+status_t
+rw_lock_read_lock(rw_lock *lock)
+{
+       MutexLocker locker(lock->lock);
+
+       if (lock->writer_count == 0) {
+               lock->reader_count++;
+               return B_OK;
+       }
+
+       if (lock->holder == find_thread(NULL)) {
+               lock->owner_count++;
+               return B_OK;
+       }
+
+       return rw_lock_wait(lock, false);
+}
+
+
+status_t
+rw_lock_read_unlock(rw_lock *lock)
+{
+       MutexLocker locker(lock->lock);
+
+       if (lock->holder == find_thread(NULL)) {
+               if (--lock->owner_count > 0)
+                       return B_OK;
+
+               // this originally has been a write lock
+               lock->writer_count--;
+               lock->holder = -1;
+
+               rw_lock_unblock(lock);
+               return B_OK;
+       }
+
+       if (lock->reader_count <= 0) {
+               debugger("rw_lock not read locked");
+               return B_ERROR;
+       }
+
+       lock->reader_count--;
+       rw_lock_unblock(lock);
+       return B_OK;
+}
+
+
+status_t
+rw_lock_write_lock(rw_lock *lock)
+{
+       MutexLocker locker(lock->lock);
+
+       if (lock->reader_count == 0 && lock->writer_count == 0) {
+               lock->writer_count++;
+               lock->holder = find_thread(NULL);
+               lock->owner_count = 1;
+               return B_OK;
+       }
+
+       if (lock->holder == find_thread(NULL)) {
+               lock->owner_count++;
+               return B_OK;
+       }
+
+       lock->writer_count++;
+
+       status_t result = rw_lock_wait(lock, true);
+       if (result != B_OK)
+               return result;
+
+       if (lock->holder != find_thread(NULL)) {
+               debugger("write locked but holder not set");
+               return B_ERROR;
+       }
+
+       lock->owner_count = 1;
+       return B_OK;
+}
+
+
+status_t
+rw_lock_write_unlock(rw_lock *lock)
+{
+       MutexLocker locker(lock->lock);
+
+       if (lock->holder != find_thread(NULL)) {
+               debugger("rw_lock not write locked");
+               return B_ERROR;
+       }
+
+       if (--lock->owner_count > 0)
+               return B_OK;
+
+       lock->writer_count--;
+       lock->holder = -1;
+       rw_lock_unblock(lock);
+       return B_OK;
+}

Modified: haiku/trunk/src/system/runtime_loader/Jamfile
===================================================================
--- haiku/trunk/src/system/runtime_loader/Jamfile       2009-11-30 08:31:31 UTC 
(rev 34363)
+++ haiku/trunk/src/system/runtime_loader/Jamfile       2009-11-30 10:29:51 UTC 
(rev 34364)
@@ -24,7 +24,8 @@
        kernel_cpp.cpp
        KMessage.cpp
        :
-       <src!system!libroot!os>locks.o
+       <src!system!libroot!os>mutex.o
+       <src!system!libroot!os>recursive_lock.o
        <src!system!libroot!os>syscalls.o
        <src!system!libroot!os>sem.o
 

Modified: haiku/trunk/src/system/runtime_loader/arch/m68k/Jamfile
===================================================================
--- haiku/trunk/src/system/runtime_loader/arch/m68k/Jamfile     2009-11-30 
08:31:31 UTC (rev 34363)
+++ haiku/trunk/src/system/runtime_loader/arch/m68k/Jamfile     2009-11-30 
10:29:51 UTC (rev 34364)
@@ -10,7 +10,6 @@
        :
        <src!system!libroot!os!arch!$(TARGET_ARCH)>atomic.o
        <src!system!libroot!os!arch!$(TARGET_ARCH)>thread.o
-       <src!system!libroot!os!arch!$(TARGET_ARCH)>tls.o
 
        <src!system!libroot!posix!string!arch!$(TARGET_ARCH)>arch_string.o
        <src!system!libroot!posix!string!arch!$(TARGET_ARCH)>memset.o

Modified: haiku/trunk/src/system/runtime_loader/arch/ppc/Jamfile
===================================================================
--- haiku/trunk/src/system/runtime_loader/arch/ppc/Jamfile      2009-11-30 
08:31:31 UTC (rev 34363)
+++ haiku/trunk/src/system/runtime_loader/arch/ppc/Jamfile      2009-11-30 
10:29:51 UTC (rev 34364)
@@ -10,7 +10,6 @@
        :
        <src!system!libroot!os!arch!$(TARGET_ARCH)>atomic.o
        <src!system!libroot!os!arch!$(TARGET_ARCH)>thread.o
-       <src!system!libroot!os!arch!$(TARGET_ARCH)>tls.o
 
        <src!system!libroot!posix!string!arch!$(TARGET_ARCH)>memcpy.o
        <src!system!libroot!posix!string!arch!$(TARGET_ARCH)>memset.o

Modified: haiku/trunk/src/system/runtime_loader/arch/x86/Jamfile
===================================================================
--- haiku/trunk/src/system/runtime_loader/arch/x86/Jamfile      2009-11-30 
08:31:31 UTC (rev 34363)
+++ haiku/trunk/src/system/runtime_loader/arch/x86/Jamfile      2009-11-30 
10:29:51 UTC (rev 34364)
@@ -10,7 +10,6 @@
        :
        <src!system!libroot!os!arch!$(TARGET_ARCH)>atomic.o
        <src!system!libroot!os!arch!$(TARGET_ARCH)>thread.o
-       <src!system!libroot!os!arch!$(TARGET_ARCH)>tls.o
 
 #      <src!system!libroot!posix!string>memcpy.o
        <src!system!libroot!posix!string!arch!$(TARGET_ARCH)>arch_string.o


Other related posts:

  • » [haiku-commits] r34364 - in haiku/trunk: headers/private/shared src/system/libroot/os src/system/libroot/os/locks src/system/runtime_loader src/system/runtime_loader/arch/m68k ... - ingo_weinhold