bool TestDegrade(TestContext& context) { TEST_ASSERT(rw_lock_write_lock(&fLock) == B_OK); TEST_ASSERT(rw_lock_read_lock(&fLock) == B_OK); rw_lock_write_unlock(&fLock); rw_lock_read_unlock(&fLock); return true; }
void Inode::WriteLockInTransaction(Transaction& transaction) { acquire_vnode(fVolume->FSVolume(), ID()); TRACE("Inode::WriteLockInTransaction(): Locking\n"); rw_lock_write_lock(&fLock); transaction.AddListener(this); }
bool TestNestedWrite(TestContext& context) { for (int32 i = 0; i < 10; i++) TEST_ASSERT(rw_lock_write_lock(&fLock) == B_OK); for (int32 i = 0; i < 10; i++) rw_lock_write_unlock(&fLock); return true; }
bool TestSimple(TestContext& context) { for (int32 i = 0; i < 3; i++) { TEST_ASSERT(rw_lock_read_lock(&fLock) == B_OK); rw_lock_read_unlock(&fLock); TEST_ASSERT(rw_lock_write_lock(&fLock) == B_OK); rw_lock_write_unlock(&fLock); } return true; }
/*static*/ void VMAddressSpace::_DeleteIfUnreferenced(team_id id) { rw_lock_write_lock(&sAddressSpaceTableLock); bool remove = false; VMAddressSpace* addressSpace = sAddressSpaceTable.Lookup(id); if (addressSpace != NULL && addressSpace->fRefCount == 0) { sAddressSpaceTable.RemoveUnchecked(addressSpace); remove = true; } rw_lock_write_unlock(&sAddressSpaceTableLock); if (remove) delete addressSpace; }
/*static*/ status_t VMAddressSpace::Create(team_id teamID, addr_t base, size_t size, bool kernel, VMAddressSpace** _addressSpace) { VMAddressSpace* addressSpace = kernel ? (VMAddressSpace*)new(std::nothrow) VMKernelAddressSpace(teamID, base, size) : (VMAddressSpace*)new(std::nothrow) VMUserAddressSpace(teamID, base, size); if (addressSpace == NULL) return B_NO_MEMORY; status_t status = addressSpace->InitObject(); if (status != B_OK) { delete addressSpace; return status; } TRACE(("VMAddressSpace::Create(): team %ld (%skernel): %#lx bytes starting at " "%#lx => %p\n", teamID, kernel ? "" : "!", size, base, addressSpace)); // create the corresponding translation map status = arch_vm_translation_map_create_map(kernel, &addressSpace->fTranslationMap); if (status != B_OK) { delete addressSpace; return status; } // add the aspace to the global hash table rw_lock_write_lock(&sAddressSpaceTableLock); sAddressSpaceTable.InsertUnchecked(addressSpace); rw_lock_write_unlock(&sAddressSpaceTableLock); *_addressSpace = addressSpace; return B_OK; }
void rw_lock_destroy(rw_lock* lock) { char* name = (lock->flags & RW_LOCK_FLAG_CLONE_NAME) != 0 ? (char*)lock->name : NULL; // unblock all waiters InterruptsSpinLocker locker(lock->lock); #if KDEBUG if (lock->waiters != NULL && thread_get_current_thread_id() != lock->holder) { panic("rw_lock_destroy(): there are blocking threads, but the caller " "doesn't hold the write lock (%p)", lock); locker.Unlock(); if (rw_lock_write_lock(lock) != B_OK) return; locker.Lock(); } #endif while (rw_lock_waiter* waiter = lock->waiters) { // dequeue lock->waiters = waiter->next; // unblock thread thread_unblock(waiter->thread, B_ERROR); } lock->name = NULL; locker.Unlock(); free(name); }
status_t ext2_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat* stat, uint32 mask) { TRACE("ext2_write_stat\n"); Volume* volume = (Volume*)_volume->private_volume; if (volume->IsReadOnly()) return B_READ_ONLY_DEVICE; Inode* inode = (Inode*)_node->private_node; ext2_inode& node = inode->Node(); bool updateTime = false; uid_t uid = geteuid(); bool isOwnerOrRoot = uid == 0 || uid == (uid_t)node.UserID(); bool hasWriteAccess = inode->CheckPermissions(W_OK) == B_OK; TRACE("ext2_write_stat: Starting transaction\n"); Transaction transaction(volume->GetJournal()); inode->WriteLockInTransaction(transaction); if ((mask & B_STAT_SIZE) != 0 && inode->Size() != stat->st_size) { if (inode->IsDirectory()) return B_IS_A_DIRECTORY; if (!inode->IsFile()) return B_BAD_VALUE; if (!hasWriteAccess) return B_NOT_ALLOWED; TRACE("ext2_write_stat: Old size: %ld, new size: %ld\n", (long)inode->Size(), (long)stat->st_size); off_t oldSize = inode->Size(); status_t status = inode->Resize(transaction, stat->st_size); if(status != B_OK) return status; if ((mask & B_STAT_SIZE_INSECURE) == 0) { rw_lock_write_unlock(inode->Lock()); inode->FillGapWithZeros(oldSize, inode->Size()); rw_lock_write_lock(inode->Lock()); } updateTime = true; } if ((mask & B_STAT_MODE) != 0) { // only the user or root can do that if (!isOwnerOrRoot) return B_NOT_ALLOWED; node.UpdateMode(stat->st_mode, S_IUMSK); updateTime = true; } if ((mask & B_STAT_UID) != 0) { // only root should be allowed if (uid != 0) return B_NOT_ALLOWED; node.SetUserID(stat->st_uid); updateTime = true; } if ((mask & B_STAT_GID) != 0) { // only the user or root can do that if (!isOwnerOrRoot) return B_NOT_ALLOWED; node.SetGroupID(stat->st_gid); updateTime = true; } if ((mask & B_STAT_MODIFICATION_TIME) != 0 || updateTime || (mask & B_STAT_CHANGE_TIME) != 0) { // the user or root can do that or any user with write access if (!isOwnerOrRoot && !hasWriteAccess) return B_NOT_ALLOWED; struct timespec newTimespec = { 0, 0}; if ((mask & B_STAT_MODIFICATION_TIME) != 0) newTimespec = stat->st_mtim; if ((mask & B_STAT_CHANGE_TIME) != 0 && stat->st_ctim.tv_sec > newTimespec.tv_sec) newTimespec = stat->st_ctim; if (newTimespec.tv_sec == 0) Inode::_BigtimeToTimespec(real_time_clock_usecs(), &newTimespec); inode->SetModificationTime(&newTimespec); } if ((mask & B_STAT_CREATION_TIME) != 0) { // the user or root can do that or any user with write access if (!isOwnerOrRoot && !hasWriteAccess) return B_NOT_ALLOWED; inode->SetCreationTime(&stat->st_crtim); } status_t status = inode->WriteBack(transaction); if (status == B_OK) status = transaction.Done(); if (status == B_OK) notify_stat_changed(volume->ID(), -1, inode->ID(), mask); return status; }