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:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user