Fixed a dead-lock that could happen if an attribute was changed and you

had some running live queries.
SimpleLock now allows nesting; added some missing atomic operations to
make its implementation as easy as possible.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1901 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-11-10 06:05:46 +00:00
parent 37935f570b
commit fb39a31ca7
3 changed files with 53 additions and 11 deletions
+25 -10
View File
@@ -10,11 +10,19 @@
#include <KernelExport.h> #include <KernelExport.h>
#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 #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 #endif
@@ -136,7 +144,6 @@ class Locker {
// expensive regarding that BeOS only allows for a total of 64k // expensive regarding that BeOS only allows for a total of 64k
// semaphores. // semaphores.
//#define FAST_LOCK
#ifdef FAST_LOCK #ifdef FAST_LOCK
class ReadWriteLock { class ReadWriteLock {
public: public:
@@ -317,35 +324,43 @@ class WriteLocked {
// A simple locking structure that doesn't use a semaphore - it's useful // A simple locking structure that doesn't use a semaphore - it's useful
// if you have to protect critical parts with a short runtime. // if you have to protect critical parts with a short runtime.
// It also allows to nest several locks for the same thread.
class SimpleLock { class SimpleLock {
public: public:
SimpleLock() SimpleLock()
: :
fLock(0), fHolder(-1),
fUnlock(0) fCount(0)
{ {
} }
status_t Lock(bigtime_t time = 500) status_t Lock(bigtime_t time = 500)
{ {
int32 turn = atomic_add(&fLock,1); int32 thisThread = find_thread(NULL);
while (turn != fUnlock) int32 current;
while ((current = atomic_test_and_set(&fHolder, thisThread, -1)) != -1) {
if (current == thisThread)
break;
snooze(time); snooze(time);
}
// ToDo: the lock cannot fail currently! We may want // ToDo: the lock cannot fail currently! We may want
// to change this // to change this
atomic_add(&fCount, 1);
return B_OK; return B_OK;
} }
void Unlock() void Unlock()
{ {
atomic_add(&fUnlock,1); if (atomic_add(&fCount, -1) == 1)
atomic_set(&fHolder, -1);
} }
private: private:
vint32 fLock; vint32 fHolder;
vint32 fUnlock; vint32 fCount;
}; };
// A convenience class to lock the SimpleLock, note the // A convenience class to lock the SimpleLock, note the
@@ -107,4 +107,31 @@ template<class Node> 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 */ #endif /* UTILITY_H */
@@ -474,7 +474,7 @@ bfs_suspend_vnode(void *_ns, void *_node)
static int static int
bfs_walk(void *_ns, void *_directory, const char *file, char **_resolvedPath, vnode_id *vnid) 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) if (_ns == NULL || _directory == NULL || file == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;