diff --git a/src/add-ons/kernel/file_systems/bfs/Lock.h b/src/add-ons/kernel/file_systems/bfs/Lock.h index 2c89f9ee60..1d97154f56 100644 --- a/src/add-ons/kernel/file_systems/bfs/Lock.h +++ b/src/add-ons/kernel/file_systems/bfs/Lock.h @@ -10,11 +10,19 @@ #include +#include "Utility.h" -// configure here if and when real benaphores should be used +// Configure here if and when real benaphores should be used +// Benaphores doesn't make much sense in the kernel, so they are only +// enabled for the user-space test application #ifdef USER -# define USE_BENAPHORE 1 +# define USE_BENAPHORE + // if defined, benaphores are used for the Semaphore class +//# define FAST_LOCK + // the ReadWriteLock class uses a second Semaphore to + // speed up locking - only makes sense if USE_BENAPHORE + // is defined, too. #endif @@ -136,7 +144,6 @@ class Locker { // expensive regarding that BeOS only allows for a total of 64k // semaphores. -//#define FAST_LOCK #ifdef FAST_LOCK class ReadWriteLock { public: @@ -317,35 +324,43 @@ class WriteLocked { // A simple locking structure that doesn't use a semaphore - it's useful // if you have to protect critical parts with a short runtime. +// It also allows to nest several locks for the same thread. class SimpleLock { public: SimpleLock() : - fLock(0), - fUnlock(0) + fHolder(-1), + fCount(0) { } status_t Lock(bigtime_t time = 500) { - int32 turn = atomic_add(&fLock,1); - while (turn != fUnlock) + int32 thisThread = find_thread(NULL); + int32 current; + while ((current = atomic_test_and_set(&fHolder, thisThread, -1)) != -1) { + if (current == thisThread) + break; + snooze(time); + } // ToDo: the lock cannot fail currently! We may want // to change this + atomic_add(&fCount, 1); return B_OK; } void Unlock() { - atomic_add(&fUnlock,1); + if (atomic_add(&fCount, -1) == 1) + atomic_set(&fHolder, -1); } private: - vint32 fLock; - vint32 fUnlock; + vint32 fHolder; + vint32 fCount; }; // A convenience class to lock the SimpleLock, note the diff --git a/src/add-ons/kernel/file_systems/bfs/Utility.h b/src/add-ons/kernel/file_systems/bfs/Utility.h index f095545a16..e42c3ef210 100644 --- a/src/add-ons/kernel/file_systems/bfs/Utility.h +++ b/src/add-ons/kernel/file_systems/bfs/Utility.h @@ -107,4 +107,31 @@ template struct list { }; +// Some atomic operations that are somehow missing in BeOS: +// +// atomic_test_and_set(value, newValue, testAgainst) +// sets "value" to "newValue", if "value" is equal to "testAgainst" +// atomic_set(value, newValue) +// sets "value" to "newValue" + +#if __INTEL__ + inline int32 + atomic_test_and_set(volatile int32 *value, int32 newValue, int32 testAgainst) + { + int32 oldValue; + asm volatile("lock; cmpxchg %%ecx, (%%edx)" + : "=a" (oldValue) : "a" (testAgainst), "c" (newValue), "d" (value)); + return oldValue; + } + + inline void + atomic_set(volatile int32 *value, int32 newValue) + { + asm volatile("lock; xchg %%eax, (%%edx)" + : : "a" (newValue), "d" (value)); + } +#else +# error The macros atomic_set(), and atomic_test_and_set() are not defined for the target processor +#endif + #endif /* UTILITY_H */ diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 72cdaf678d..e5b38fa11d 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -474,7 +474,7 @@ bfs_suspend_vnode(void *_ns, void *_node) static int bfs_walk(void *_ns, void *_directory, const char *file, char **_resolvedPath, vnode_id *vnid) { - FUNCTION_START(("file = %s\n",file)); + //FUNCTION_START(("file = %s\n",file)); if (_ns == NULL || _directory == NULL || file == NULL) return B_BAD_VALUE;