* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Vnode.h"
#include <util/AutoLock.h>
vnode::Bucket vnode::sBuckets[kBucketCount];
vnode::Bucket::Bucket()
{
mutex_init(&lock, "vnode bucket");
}
void
vnode::StaticInit()
{
for (uint32 i = 0; i < kBucketCount; i++)
new(&sBuckets[i]) Bucket;
}
void
vnode::_WaitForLock()
{
LockWaiter waiter;
waiter.thread = thread_get_current_thread();
waiter.vnode = this;
Bucket& bucket = _Bucket();
MutexLocker bucketLocker(bucket.lock);
if ((atomic_or(&fFlags, kFlagsWaitingLocker)
& (kFlagsLocked | kFlagsWaitingLocker)) == 0) {
atomic_or(&fFlags, kFlagsLocked);
atomic_and(&fFlags, ~kFlagsWaitingLocker);
return;
}
bucket.waiters.Add(&waiter);
thread_prepare_to_block(waiter.thread, 0, THREAD_BLOCK_TYPE_OTHER,
"vnode lock");
bucketLocker.Unlock();
thread_block();
}
void
vnode::_WakeUpLocker()
{
Bucket& bucket = _Bucket();
MutexLocker bucketLocker(bucket.lock);
atomic_or(&fFlags, kFlagsLocked);
LockWaiter* waiter = NULL;
bool onlyWaiter = true;
for (LockWaiterList::Iterator it = bucket.waiters.GetIterator();
LockWaiter* someWaiter = it.Next();) {
if (someWaiter->vnode == this) {
if (waiter != NULL) {
onlyWaiter = false;
break;
}
waiter = someWaiter;
it.Remove();
}
}
ASSERT(waiter != NULL);
if (onlyWaiter)
atomic_and(&fFlags, ~kFlagsWaitingLocker);
thread_unblock(waiter->thread, B_OK);
}