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

View File

@ -10,11 +10,19 @@
#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
# 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

View File

@ -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 */

View File

@ -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;