* Removed the home-brewn locking classes in BFS besides the read/write lock

(for now).
* Inode::fSmallDataLock is now a recursive_lock, Journal::fLock is now
  a recursive_lock, too, Journal::fEntriesLock is now a mutex, as is
  BPlusTree::fIteratorLock.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26298 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-07-07 16:21:00 +00:00
parent af370c702a
commit 03fa417b70
18 changed files with 101 additions and 391 deletions
+2 -3
View File
@@ -1,8 +1,7 @@
SubDir HAIKU_TOP src add-ons disk_systems bfs ;
UsePrivateHeaders kernel ;
UsePrivateHeaders shared ;
UsePrivateHeaders storage ;
UsePrivateKernelHeaders ;
UsePrivateHeaders shared storage ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems bfs ] ;
@@ -79,13 +79,13 @@ Attribute::Get(const char *name)
fName = name;
// try to find it in the small data region
if (fInode->SmallDataLock().Lock() == B_OK) {
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
fNodeGetter.SetToNode(fInode);
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char *)name);
if (fSmall != NULL)
return B_OK;
fInode->SmallDataLock().Unlock();
recursive_lock_unlock(&fInode->SmallDataLock());
fNodeGetter.Unset();
}
@@ -98,7 +98,7 @@ void
Attribute::Put()
{
if (fSmall != NULL) {
fInode->SmallDataLock().Unlock();
recursive_lock_unlock(&fInode->SmallDataLock());
fNodeGetter.Unset();
fSmall = NULL;
}
@@ -195,7 +195,7 @@ Attribute::Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length)
if (fSmall == NULL && fAttribute == NULL)
return B_NO_INIT;
// ToDo: move small_data logic from Inode::ReadAttribute() over to here!
// TODO: move small_data logic from Inode::ReadAttribute() over to here!
return fInode->ReadAttribute(cookie->name, 0, pos, buffer, _length);
}
@@ -341,6 +341,7 @@ BPlusTree::BPlusTree(Transaction &transaction, Inode *stream, int32 nodeSize)
fHeader(NULL),
fCachedHeader(this)
{
mutex_init(&fIteratorLock, "bfs b+tree iterator");
SetTo(transaction, stream);
}
@@ -351,6 +352,7 @@ BPlusTree::BPlusTree(Inode *stream)
fHeader(NULL),
fCachedHeader(this)
{
mutex_init(&fIteratorLock, "bfs b+tree iterator");
SetTo(stream);
}
@@ -364,6 +366,7 @@ BPlusTree::BPlusTree()
fAllowDuplicates(true),
fStatus(B_NO_INIT)
{
mutex_init(&fIteratorLock, "bfs b+tree iterator");
}
@@ -372,14 +375,13 @@ BPlusTree::~BPlusTree()
// if there are any TreeIterators left, we need to stop them
// (can happen when the tree's inode gets deleted while
// traversing the tree - a TreeIterator doesn't lock the inode)
if (fIteratorLock.Lock() < B_OK)
return;
mutex_lock(&fIteratorLock);
TreeIterator *iterator = NULL;
while ((iterator = fIterators.Next(iterator)) != NULL)
iterator->Stop();
fIteratorLock.Unlock();
mutex_destroy(&fIteratorLock);
}
@@ -565,38 +567,27 @@ BPlusTree::_UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex,
// Although every iterator which is affected by this update currently
// waits on a semaphore, other iterators could be added/removed at
// any time, so we need to protect this loop
if (fIteratorLock.Lock() < B_OK)
return;
MutexLocker _(fIteratorLock);
TreeIterator *iterator = NULL;
while ((iterator = fIterators.Next(iterator)) != NULL)
iterator->Update(offset, nextOffset, keyIndex, splitAt, change);
fIteratorLock.Unlock();
}
void
BPlusTree::_AddIterator(TreeIterator *iterator)
{
if (fIteratorLock.Lock() < B_OK)
return;
MutexLocker _(fIteratorLock);
fIterators.Add(iterator);
fIteratorLock.Unlock();
}
void
BPlusTree::_RemoveIterator(TreeIterator *iterator)
{
if (fIteratorLock.Lock() < B_OK)
return;
MutexLocker _(fIteratorLock);
fIterators.Remove(iterator);
fIteratorLock.Unlock();
}
@@ -2139,7 +2130,8 @@ TreeIterator::SkipDuplicates()
void
TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt, int8 change)
TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex,
uint16 splitAt, int8 change)
{
if (offset != fCurrentNodeOffset)
return;
@@ -2158,7 +2150,7 @@ TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 spl
if (keyIndex <= fCurrentKey)
fCurrentKey += change;
// ToDo: duplicate handling!
// TODO: duplicate handling!
}
@@ -273,7 +273,7 @@ class BPlusTree {
int32 fNodeSize;
bool fAllowDuplicates;
status_t fStatus;
SimpleLock fIteratorLock;
mutex fIteratorLock;
Chain<TreeIterator> fIterators;
};
@@ -441,15 +441,16 @@ AllocationGroup::Free(Transaction &transaction, uint16 start, int32 length)
BlockAllocator::BlockAllocator(Volume *volume)
:
fVolume(volume),
fLock("bfs allocator"),
fGroups(NULL),
fCheckBitmap(NULL)
{
mutex_init(&fLock, "bfs allocator");
}
BlockAllocator::~BlockAllocator()
{
mutex_destroy(&fLock);
delete[] fGroups;
}
@@ -457,9 +458,6 @@ BlockAllocator::~BlockAllocator()
status_t
BlockAllocator::Initialize(bool full)
{
if (fLock.InitCheck() < B_OK)
return B_ERROR;
fNumGroups = fVolume->AllocationGroups();
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
fGroups = new AllocationGroup[fNumGroups];
@@ -469,8 +467,8 @@ BlockAllocator::Initialize(bool full)
if (!full)
return B_OK;
fLock.Lock();
// the lock will be released by the initialize() function
mutex_lock(&fLock);
// the lock will be released by the _Initialize() method
thread_id id = spawn_kernel_thread((thread_func)BlockAllocator::_Initialize,
"bfs block allocator", B_LOW_PRIORITY, (void *)this);
@@ -547,7 +545,7 @@ BlockAllocator::_Initialize(BlockAllocator *allocator)
uint32 *buffer = (uint32 *)malloc(blocks << blockShift);
if (buffer == NULL) {
allocator->fLock.Unlock();
mutex_unlock(&allocator->fLock);
RETURN_ERROR(B_NO_MEMORY);
}
@@ -621,7 +619,7 @@ BlockAllocator::_Initialize(BlockAllocator *allocator)
volume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
}
allocator->fLock.Unlock();
mutex_unlock(&allocator->fLock);
return B_OK;
}
@@ -636,7 +634,7 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
FUNCTION_START(("group = %ld, start = %u, maximum = %u, minimum = %u\n", group, start, maximum, minimum));
AllocationBlock cached(fVolume);
Locker lock(fLock);
MutexLocker lock(fLock);
// The first scan through all allocation groups will look for the
// wanted maximum of blocks, the second scan will just look to
@@ -821,7 +819,7 @@ BlockAllocator::Allocate(Transaction &transaction, Inode *inode, off_t numBlocks
status_t
BlockAllocator::Free(Transaction &transaction, block_run run)
{
Locker lock(fLock);
MutexLocker lock(fLock);
int32 group = run.AllocationGroup();
uint16 start = run.Start();
@@ -896,14 +894,14 @@ BlockAllocator::StartChecking(check_control *control)
if (!_IsValidCheckControl(control))
return B_BAD_VALUE;
status_t status = fLock.Lock();
status_t status = mutex_lock(&fLock);
if (status < B_OK)
return status;
size_t size = BitmapSize();
fCheckBitmap = (uint32 *)malloc(size);
if (fCheckBitmap == NULL) {
fLock.Unlock();
mutex_unlock(&fLock);
return B_NO_MEMORY;
}
@@ -911,7 +909,7 @@ BlockAllocator::StartChecking(check_control *control)
if (cookie == NULL) {
free(fCheckBitmap);
fCheckBitmap = NULL;
fLock.Unlock();
mutex_unlock(&fLock);
return B_NO_MEMORY;
}
@@ -1013,7 +1011,7 @@ BlockAllocator::StopChecking(check_control *control)
fCheckBitmap = NULL;
fCheckCookie = NULL;
delete cookie;
fLock.Unlock();
mutex_unlock(&fLock);
return B_OK;
}
@@ -1113,7 +1111,7 @@ BlockAllocator::CheckNextNode(check_control *control)
// check if the inode's name is the same as in the b+tree
if (inode->IsRegularNode()) {
SimpleLocker locker(inode->SmallDataLock());
RecursiveLocker locker(inode->SmallDataLock());
NodeGetter node(fVolume, inode);
const char *localName = inode->Name(node.Node());
@@ -6,7 +6,7 @@
#define BLOCK_ALLOCATOR_H
#include "Lock.h"
#include "system_dependencies.h"
class AllocationGroup;
@@ -57,7 +57,7 @@ class BlockAllocator {
static status_t _Initialize(BlockAllocator *);
Volume *fVolume;
Semaphore fLock;
mutex fLock;
AllocationGroup *fGroups;
int32 fNumGroups;
uint32 fBlocksPerGroup;
+19 -26
View File
@@ -330,6 +330,8 @@ Inode::Inode(Volume *volume, ino_t id)
(int)BlockRun().AllocationGroup(), BlockRun().Start());
fLock.Initialize(lockName);
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
// these two will help to maintain the indices
fOldSize = Size();
fOldLastModified = LastModified();
@@ -361,6 +363,8 @@ Inode::Inode(Volume *volume, Transaction &transaction, ino_t id, mode_t mode,
(int)run.AllocationGroup(), run.Start());
fLock.Initialize(lockName);
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
NodeGetter node(volume, transaction, this, true);
memset(&fNode, 0, sizeof(bfs_inode));
@@ -482,24 +486,16 @@ Inode::CheckPermissions(int accessMode) const
void
Inode::_AddIterator(AttributeIterator *iterator)
{
if (fSmallDataLock.Lock() < B_OK)
return;
RecursiveLocker _(fSmallDataLock);
fIterators.Add(iterator);
fSmallDataLock.Unlock();
}
void
Inode::_RemoveIterator(AttributeIterator *iterator)
{
if (fSmallDataLock.Lock() < B_OK)
return;
RecursiveLocker _(fSmallDataLock);
fIterators.Remove(iterator);
fSmallDataLock.Unlock();
}
@@ -511,7 +507,7 @@ status_t
Inode::_MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node,
const char *name, int32 bytes)
{
ASSERT(fSmallDataLock.IsLocked());
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
while (bytes > 0) {
small_data *item = node->SmallDataStart(), *max = NULL;
@@ -575,7 +571,7 @@ Inode::_MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node,
status_t
Inode::_RemoveSmallData(bfs_inode *node, small_data *item, int32 index)
{
ASSERT(fSmallDataLock.IsLocked());
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
small_data *next = item->Next();
if (!next->IsLast(node)) {
@@ -617,7 +613,7 @@ Inode::_RemoveSmallData(Transaction &transaction, NodeGetter &nodeGetter,
return B_BAD_VALUE;
bfs_inode *node = nodeGetter.WritableNode();
SimpleLocker locker(fSmallDataLock);
RecursiveLocker locker(fSmallDataLock);
// search for the small_data item
@@ -668,7 +664,7 @@ Inode::_AddSmallData(Transaction &transaction, NodeGetter &nodeGetter,
return B_DEVICE_FULL;
nodeGetter.MakeWritable(transaction);
SimpleLocker locker(fSmallDataLock);
RecursiveLocker locker(fSmallDataLock);
// Find the last item or one with the same name we have to add
small_data *item = node->SmallDataStart();
@@ -809,7 +805,7 @@ Inode::_GetNextSmallData(bfs_inode *node, small_data **_smallData) const
if (node == NULL)
RETURN_ERROR(B_BAD_VALUE);
ASSERT(fSmallDataLock.IsLocked());
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
small_data *data = *_smallData;
@@ -836,7 +832,7 @@ Inode::_GetNextSmallData(bfs_inode *node, small_data **_smallData) const
small_data *
Inode::FindSmallData(const bfs_inode *node, const char *name) const
{
ASSERT(fSmallDataLock.IsLocked());
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
small_data *smallData = NULL;
while (_GetNextSmallData(const_cast<bfs_inode *>(node), &smallData)
@@ -855,7 +851,7 @@ Inode::FindSmallData(const bfs_inode *node, const char *name) const
const char *
Inode::Name(const bfs_inode *node) const
{
ASSERT(fSmallDataLock.IsLocked());
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
small_data *smallData = NULL;
while (_GetNextSmallData((bfs_inode *)node, &smallData) == B_OK) {
@@ -874,7 +870,7 @@ status_t
Inode::GetName(char *buffer, size_t size) const
{
NodeGetter node(fVolume, this);
SimpleLocker locker(fSmallDataLock);
RecursiveLocker locker(fSmallDataLock);
const char *name = Name(node.Node());
if (name == NULL)
@@ -966,7 +962,7 @@ Inode::ReadAttribute(const char *name, int32 type, off_t pos, uint8 *buffer,
// search in the small_data section (which has to be locked first)
{
NodeGetter node(fVolume, this);
SimpleLocker locker(fSmallDataLock);
RecursiveLocker locker(fSmallDataLock);
small_data *smallData = FindSmallData(node.Node(), name);
if (smallData != NULL) {
@@ -1025,7 +1021,7 @@ Inode::WriteAttribute(Transaction &transaction, const char *name, int32 type,
if (GetAttribute(name, &attribute) < B_OK) {
// save the old attribute data
NodeGetter node(fVolume, transaction, this);
fSmallDataLock.Lock();
recursive_lock_lock(&fSmallDataLock);
small_data *smallData = FindSmallData(node.Node(), name);
if (smallData != NULL) {
@@ -1036,7 +1032,7 @@ Inode::WriteAttribute(Transaction &transaction, const char *name, int32 type,
memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
}
}
fSmallDataLock.Unlock();
recursive_lock_unlock(&fSmallDataLock);
// if the attribute doesn't exist yet (as a file), try to put it in the
// small_data section first - if that fails (due to insufficent space),
@@ -1128,7 +1124,7 @@ Inode::RemoveAttribute(Transaction &transaction, const char *name)
// update index for attributes in the small_data section
{
fSmallDataLock.Lock();
RecursiveLocker _(fSmallDataLock);
small_data *smallData = FindSmallData(node.Node(), name);
if (smallData != NULL) {
@@ -1138,7 +1134,6 @@ Inode::RemoveAttribute(Transaction &transaction, const char *name)
index.Update(transaction, name, smallData->Type(),
smallData->Data(), length, NULL, 0, this);
}
fSmallDataLock.Unlock();
}
status_t status = _RemoveSmallData(transaction, node, name);
@@ -2561,7 +2556,7 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type,
const bfs_inode *node = nodeGetter.Node();
const small_data *item = ((bfs_inode *)node)->SmallDataStart();
fInode->SmallDataLock().Lock();
RecursiveLocker _(&fInode->SmallDataLock());
int32 i = 0;
for (;;item = item->Next()) {
@@ -2589,8 +2584,6 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type,
fCurrentSmallData = -1;
}
fInode->SmallDataLock().Unlock();
if (fCurrentSmallData != -1)
return B_OK;
}
+2 -2
View File
@@ -46,7 +46,7 @@ class Inode {
off_t BlockNumber() const { return fVolume->VnodeToBlock(fID); }
ReadWriteLock &Lock() { return fLock; }
SimpleLock &SmallDataLock() { return fSmallDataLock; }
recursive_lock &SmallDataLock() { return fSmallDataLock; }
status_t WriteBack(Transaction &transaction);
bool IsContainer() const
@@ -207,7 +207,7 @@ class Inode {
// we need those values to ensure we will remove
// the correct keys from the indices
mutable SimpleLock fSmallDataLock;
mutable recursive_lock fSmallDataLock;
Chain<AttributeIterator> fIterators;
};
+2 -3
View File
@@ -24,10 +24,9 @@ SubDir HAIKU_TOP src add-ons kernel file_systems bfs ;
SubDirC++Flags $(defines) -Wall -Wno-multichar ;
}
UsePrivateHeaders [ FDirName kernel ] ; # For kernel_cpp.cpp
UsePrivateKernelHeaders ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders [ FDirName shared ] ;
UsePrivateHeaders [ FDirName storage ] ;
UsePrivateHeaders shared storage ;
KernelAddon bfs :
bfs_disk_system.cpp
+20 -15
View File
@@ -395,7 +395,6 @@ RunArrays::MaxArrayLength()
Journal::Journal(Volume *volume)
:
fVolume(volume),
fLock("bfs journal"),
fOwner(NULL),
fLogSize(volume->Log().Length()),
fMaxTransactionSize(fLogSize / 2 - 5),
@@ -403,19 +402,24 @@ Journal::Journal(Volume *volume)
fUnwrittenTransactions(0),
fHasSubtransaction(false)
{
recursive_lock_init(&fLock, "bfs journal");
mutex_init(&fEntriesLock, "bfs journal entries");
}
Journal::~Journal()
{
FlushLogAndBlocks();
recursive_lock_destroy(&fLock);
mutex_destroy(&fEntriesLock);
}
status_t
Journal::InitCheck()
{
return fLock.InitCheck();
return B_OK;
}
@@ -605,7 +609,7 @@ Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
// Set log_start pointer if possible...
journal->fEntriesLock.Lock();
mutex_lock(&journal->fEntriesLock);
if (logEntry == journal->fEntries.First()) {
LogEntry *next = journal->fEntries.GetNext(logEntry);
@@ -624,7 +628,7 @@ Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
journal->fUsed -= logEntry->Length();
journal->fEntries.Remove(logEntry);
journal->fEntriesLock.Unlock();
mutex_unlock(&journal->fEntriesLock);
delete logEntry;
@@ -839,10 +843,10 @@ Journal::_WriteTransactionToLog()
// at this point, we can finally end the transaction - we're in
// a guaranteed valid state
fEntriesLock.Lock();
mutex_lock(&fEntriesLock);
fEntries.Add(logEntry);
fUsed += logEntry->Length();
fEntriesLock.Unlock();
mutex_unlock(&fEntriesLock);
if (detached) {
fTransactionID = cache_detach_sub_transaction(fVolume->BlockCache(),
@@ -864,13 +868,14 @@ Journal::_WriteTransactionToLog()
status_t
Journal::_FlushLog(bool canWait, bool flushBlocks)
{
status_t status = canWait ? fLock.Lock() : fLock.LockWithTimeout(0);
status_t status = canWait ? recursive_lock_lock(&fLock)
: recursive_lock_trylock(&fLock);
if (status != B_OK)
return status;
if (fLock.OwnerCount() > 1) {
if (recursive_lock_get_recursion(&fLock) > 1) {
// whoa, FlushLogAndBlocks() was called from inside a transaction
fLock.Unlock();
recursive_lock_unlock(&fLock);
return B_OK;
}
@@ -885,7 +890,7 @@ Journal::_FlushLog(bool canWait, bool flushBlocks)
if (flushBlocks)
status = fVolume->FlushDevice();
fLock.Unlock();
recursive_lock_unlock(&fLock);
return status;
}
@@ -903,11 +908,11 @@ Journal::FlushLogAndBlocks()
status_t
Journal::Lock(Transaction *owner)
{
status_t status = fLock.Lock();
status_t status = recursive_lock_lock(&fLock);
if (status != B_OK)
return status;
if (fLock.OwnerCount() > 1) {
if (recursive_lock_get_recursion(&fLock) > 1) {
// we'll just use the current transaction again
return B_OK;
}
@@ -929,7 +934,7 @@ Journal::Lock(Transaction *owner)
fTransactionID = cache_start_transaction(fVolume->BlockCache());
if (fTransactionID < B_OK) {
fLock.Unlock();
recursive_lock_unlock(&fLock);
return fTransactionID;
}
@@ -943,7 +948,7 @@ Journal::Lock(Transaction *owner)
void
Journal::Unlock(Transaction *owner, bool success)
{
if (fLock.OwnerCount() == 1) {
if (recursive_lock_get_recursion(&fLock) == 1) {
// we only end the transaction if we would really unlock it
// ToDo: what about failing transactions that do not unlock?
_TransactionDone(success);
@@ -952,7 +957,7 @@ Journal::Unlock(Transaction *owner, bool success)
fOwner = NULL;
}
fLock.Unlock();
recursive_lock_unlock(&fLock);
}
@@ -14,6 +14,7 @@
#include "Volume.h"
#include "Chain.h"
#include "Lock.h"
#include "Utility.h"
@@ -69,11 +70,11 @@ class Journal {
void *_journal);
Volume *fVolume;
RecursiveLock fLock;
recursive_lock fLock;
Transaction *fOwner;
uint32 fLogSize, fMaxTransactionSize, fUsed;
int32 fUnwrittenTransactions;
SimpleLock fEntriesLock;
mutex fEntriesLock;
LogEntryList fEntries;
bigtime_t fTimestamp;
int32 fTransactionID;
+1 -269
View File
@@ -26,201 +26,7 @@
# error implement recursive write locking first
#endif
class Semaphore {
public:
Semaphore(const char *name)
:
#ifdef USE_BENAPHORE
fSemaphore(create_sem(0, name)),
fCount(1)
#else
fSemaphore(create_sem(1, name))
#endif
{
}
~Semaphore()
{
delete_sem(fSemaphore);
}
status_t InitCheck()
{
if (fSemaphore < B_OK)
return fSemaphore;
return B_OK;
}
status_t Lock()
{
#ifdef USE_BENAPHORE
if (atomic_add(&fCount, -1) <= 0)
#endif
return acquire_sem(fSemaphore);
#ifdef USE_BENAPHORE
return B_OK;
#endif
}
status_t Unlock()
{
#ifdef USE_BENAPHORE
if (atomic_add(&fCount, 1) < 0)
#endif
return release_sem(fSemaphore);
#ifdef USE_BENAPHORE
return B_OK;
#endif
}
private:
sem_id fSemaphore;
#ifdef USE_BENAPHORE
vint32 fCount;
#endif
};
// a convenience class to lock a Semaphore object
class Locker {
public:
Locker(Semaphore &lock)
: fLock(lock)
{
fStatus = lock.Lock();
ASSERT(fStatus == B_OK);
}
~Locker()
{
if (fStatus == B_OK)
fLock.Unlock();
}
status_t Status() const
{
return fStatus;
}
private:
Semaphore &fLock;
status_t fStatus;
};
// #pragma mark - Recursive Lock
class RecursiveLock {
public:
RecursiveLock(const char *name)
:
#ifdef USE_BENAPHORE
fSemaphore(create_sem(0, name)),
fCount(1),
#else
fSemaphore(create_sem(1, name)),
#endif
fOwner(-1)
{
}
status_t InitCheck() const
{
if (fSemaphore < B_OK)
return fSemaphore;
return B_OK;
}
status_t LockWithTimeout(bigtime_t timeout)
{
thread_id thread = find_thread(NULL);
if (thread == fOwner) {
fOwnerCount++;
return B_OK;
}
status_t status;
#ifdef USE_BENAPHORE
if (atomic_add(&fCount, -1) > 0)
status = B_OK;
else
#endif
status = acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, timeout);
if (status == B_OK) {
fOwner = thread;
fOwnerCount = 1;
}
return status;
}
status_t Lock()
{
return LockWithTimeout(B_INFINITE_TIMEOUT);
}
status_t Unlock()
{
thread_id thread = find_thread(NULL);
if (thread != fOwner) {
panic("RecursiveLock unlocked by %d, owned by %d\n", (int)thread, (int)fOwner);
}
if (--fOwnerCount == 0) {
fOwner = -1;
#ifdef USE_BENAPHORE
if (atomic_add(&fCount, 1) < 0)
#endif
return release_sem(fSemaphore);
}
return B_OK;
}
thread_id Owner() const { return fOwner; }
int32 OwnerCount() const { return fOwnerCount; }
private:
sem_id fSemaphore;
#ifdef USE_BENAPHORE
vint32 fCount;
#endif
thread_id fOwner;
int32 fOwnerCount;
};
// a convenience class to lock an RecursiveLock object
class RecursiveLocker {
public:
RecursiveLocker(RecursiveLock &lock)
: fLock(lock)
{
fStatus = lock.Lock();
ASSERT(fStatus == B_OK);
}
~RecursiveLocker()
{
if (fStatus == B_OK)
fLock.Unlock();
}
status_t Status() const
{
return fStatus;
}
private:
RecursiveLock &fLock;
status_t fStatus;
};
//**** Many Reader/Single Writer Lock
// #pragma mark - Many Reader/Single Writer Lock
// This is a "fast" implementation of a single writer/many reader
// locking scheme. It's fast because it uses the benaphore idea
@@ -523,78 +329,4 @@ class WriteLocked {
status_t fStatus;
};
// 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()
:
fHolder(-1),
fCount(0)
{
}
status_t Lock(bigtime_t time = 500)
{
int32 thisThread = find_thread(NULL);
int32 current;
while (1) {
/*if (fHolder == -1) {
current = fHolder;
fHolder = thisThread;
}*/
current = atomic_test_and_set(&fHolder, thisThread, -1);
if (current == -1)
break;
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()
{
if (atomic_add(&fCount, -1) == 1)
atomic_set(&fHolder, -1);
}
bool IsLocked() const
{
return fHolder == find_thread(NULL);
}
private:
vint32 fHolder;
vint32 fCount;
};
// A convenience class to lock the SimpleLock, note the
// different timing compared to the direct call
class SimpleLocker {
public:
SimpleLocker(SimpleLock &lock,bigtime_t time = 1000)
: fLock(lock)
{
lock.Lock(time);
}
~SimpleLocker()
{
fLock.Unlock();
}
private:
SimpleLock &fLock;
};
#endif /* LOCK_H */
@@ -805,13 +805,13 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
// we need to lock before accessing Inode::Name()
nodeGetter.SetToNode(inode);
inode->SmallDataLock().Lock();
recursive_lock_lock(&inode->SmallDataLock());
locked = true;
// if not, check for "fake" attributes, "name", "size", "last_modified",
buffer = (uint8 *)inode->Name(nodeGetter.Node());
if (buffer == NULL) {
inode->SmallDataLock().Unlock();
recursive_lock_unlock(&inode->SmallDataLock());
return B_ERROR;
}
@@ -837,7 +837,7 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
nodeGetter.SetToNode(inode);
Inode *attribute;
inode->SmallDataLock().Lock();
recursive_lock_lock(&inode->SmallDataLock());
small_data *smallData = inode->FindSmallData(nodeGetter.Node(), fAttribute);
if (smallData != NULL) {
buffer = smallData->Data();
@@ -846,7 +846,7 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
locked = true;
} else {
// needed to unlock the small_data section as fast as possible
inode->SmallDataLock().Unlock();
recursive_lock_unlock(&inode->SmallDataLock());
nodeGetter.Unset();
if (inode->GetAttribute(fAttribute, &attribute) == B_OK) {
@@ -872,7 +872,7 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
status = CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
if (locked)
inode->SmallDataLock().Unlock();
recursive_lock_unlock(&inode->SmallDataLock());
RETURN_ERROR(status);
}
+6 -15
View File
@@ -276,18 +276,20 @@ Volume::Volume(fs_volume *volume)
:
fVolume(volume),
fBlockAllocator(this),
fLock("bfs volume"),
fRootNode(NULL),
fIndicesNode(NULL),
fDirtyCachedBlocks(0),
fUniqueID(0),
fFlags(0)
{
mutex_init(&fLock, "bfs volume");
mutex_init(&fQueryLock, "bfs queries");
}
Volume::~Volume()
{
mutex_destroy(&fLock);
}
@@ -516,16 +518,13 @@ Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
const uint8 *oldKey, size_t oldLength, const uint8 *newKey,
size_t newLength)
{
if (fQueryLock.Lock() < B_OK)
return;
MutexLocker _(fQueryLock);
Query *query = NULL;
while ((query = fQueries.Next(query)) != NULL) {
query->LiveUpdate(inode, attribute, type, oldKey, oldLength, newKey,
newLength);
}
fQueryLock.Unlock();
}
@@ -545,24 +544,16 @@ Volume::CheckForLiveQuery(const char *attribute)
void
Volume::AddQuery(Query *query)
{
if (fQueryLock.Lock() < B_OK)
return;
MutexLocker _(fQueryLock);
fQueries.Add(query);
fQueryLock.Unlock();
}
void
Volume::RemoveQuery(Query *query)
{
if (fQueryLock.Lock() < B_OK)
return;
MutexLocker _(fQueryLock);
fQueries.Remove(query);
fQueryLock.Unlock();
}
+5 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#ifndef VOLUME_H
@@ -37,7 +37,7 @@ class Volume {
bool IsValidSuperBlock();
bool IsReadOnly() const;
void Panic();
RecursiveLock &Lock();
mutex &Lock();
block_run Root() const { return fSuperBlock.root_dir; }
Inode *RootNode() const { return fRootNode; }
@@ -117,7 +117,7 @@ class Volume {
uint32 fAllocationGroupShift;
BlockAllocator fBlockAllocator;
RecursiveLock fLock;
mutex fLock;
Journal *fJournal;
vint32 fLogStart, fLogEnd;
@@ -126,7 +126,7 @@ class Volume {
vint32 fDirtyCachedBlocks;
SimpleLock fQueryLock;
mutex fQueryLock;
Chain<Query> fQueries;
int32 fUniqueID;
@@ -145,7 +145,7 @@ Volume::IsReadOnly() const
}
inline RecursiveLock &
inline mutex &
Volume::Lock()
{
return fLock;
@@ -149,7 +149,7 @@ bfs_read_fs_stat(fs_volume *_volume, struct fs_info *info)
FUNCTION();
Volume *volume = (Volume *)_volume->private_volume;
RecursiveLocker locker(volume->Lock());
MutexLocker locker(volume->Lock());
// File system flags.
info->flags = B_FS_IS_PERSISTENT | B_FS_HAS_ATTR | B_FS_HAS_MIME
@@ -181,7 +181,7 @@ bfs_write_fs_stat(fs_volume *_volume, const struct fs_info *info, uint32 mask)
if (volume->IsReadOnly())
return B_READ_ONLY_DEVICE;
RecursiveLocker locker(volume->Lock());
MutexLocker locker(volume->Lock());
status_t status = B_BAD_VALUE;
@@ -12,6 +12,7 @@
#else // !BFS_SHELL
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>
#include <util/kernel_cpp.h>
#include <util/Stack.h>
@@ -1,8 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems bfs ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders kernel shared storage ;
UsePrivateKernelHeaders ;
UsePrivateHeaders shared storage ;
SubDirHdrs $(HAIKU_TOP) src add-ons kernel file_systems bfs ;