From 07646c514ab6978111f36c63bf72a85b1d876ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 14 Mar 2005 01:37:48 +0000 Subject: [PATCH] The write lock of ReadWriteLock can now be held recursively; ie. you can hold the lock and still call subsequent Lock() and LockWrite() without the deadlock penalty. Added another constructor to WriteLocked so that you can also pass NULL to it (in this case, nothing happens, of course :)). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11720 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/file_systems/bfs/Lock.h | 53 ++++++++++++++++------ 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/Lock.h b/src/add-ons/kernel/file_systems/bfs/Lock.h index 2dda801fd4..089804c9c3 100644 --- a/src/add-ons/kernel/file_systems/bfs/Lock.h +++ b/src/add-ons/kernel/file_systems/bfs/Lock.h @@ -24,7 +24,9 @@ // speed up locking - only makes sense if USE_BENAPHORE // is defined, too. #endif - +#ifdef FAST_LOCK +# error implement recursive write locking first +#endif class Semaphore { public: @@ -164,13 +166,7 @@ class RecursiveLock { { thread_id thread = find_thread(NULL); if (thread != fOwner) { - #if __MWERKS__ && !USER //--- The R5 PowerPC kernel doesn't have panic() - char blip[255]; - sprintf(blip,"RecursiveLock unlocked by %ld, owned by %ld\n", thread, fOwner); - kernel_debugger(blip); - #else - panic("RecursiveLock unlocked by %ld, owned by %ld\n", thread, fOwner); - #endif + panic("RecursiveLock unlocked by %ld, owned by %ld\n", thread, fOwner); } if (--fOwnerCount == 0) { @@ -379,22 +375,44 @@ class ReadWriteLock { status_t Lock() { + thread_id currentThread = find_thread(NULL); + if (currentThread == fOwner) { + fOwnerCount++; + return B_OK; + } return acquire_sem(fSemaphore); } void Unlock() { + thread_id currentThread = find_thread(NULL); + if (fOwner == currentThread && --fOwnerCount > 0) + return; + release_sem(fSemaphore); } status_t LockWrite() { - return acquire_sem_etc(fSemaphore, MAX_READERS, 0, 0); + thread_id currentThread = find_thread(NULL); + if (currentThread == fOwner) { + fOwnerCount++; + return B_OK; + } + status_t status = acquire_sem_etc(fSemaphore, MAX_READERS, 0, 0); + if (status >= B_OK) { + fOwner = currentThread; + fOwnerCount = 1; + } + return status; } void UnlockWrite() { - release_sem_etc(fSemaphore, MAX_READERS, 0); + if (--fOwnerCount == 0) { + fOwner = -1; + release_sem_etc(fSemaphore, MAX_READERS, 0); + } } private: @@ -402,6 +420,8 @@ class ReadWriteLock { friend class WriteLocked; sem_id fSemaphore; + thread_id fOwner; + int32 fOwnerCount; }; #endif // FAST_LOCK @@ -431,15 +451,22 @@ class WriteLocked { public: WriteLocked(ReadWriteLock &lock) : - fLock(lock) + fLock(&lock) { fStatus = lock.LockWrite(); } + WriteLocked(ReadWriteLock *lock) + : + fLock(lock) + { + fStatus = lock != NULL ? lock->LockWrite() : B_ERROR; + } + ~WriteLocked() { if (fStatus == B_OK) - fLock.UnlockWrite(); + fLock->UnlockWrite(); } status_t IsLocked() @@ -448,7 +475,7 @@ class WriteLocked { } private: - ReadWriteLock &fLock; + ReadWriteLock *fLock; status_t fStatus; };