/* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef VM_ADDRESS_SPACE_LOCKING_H #define VM_ADDRESS_SPACE_LOCKING_H #include #include struct VMAddressSpace; struct VMArea; struct VMCache; class AddressSpaceLockerBase { public: static VMAddressSpace* GetAddressSpaceByAreaID(area_id id); }; class AddressSpaceReadLocker : private AddressSpaceLockerBase { public: AddressSpaceReadLocker(team_id team); AddressSpaceReadLocker(VMAddressSpace* space, bool getNewReference); AddressSpaceReadLocker(); ~AddressSpaceReadLocker(); status_t SetTo(team_id team); void SetTo(VMAddressSpace* space, bool getNewReference); status_t SetFromArea(area_id areaID, VMArea*& area); bool IsLocked() const { return fLocked; } bool Lock(); void Unlock(); void Unset(); VMAddressSpace* AddressSpace() const { return fSpace; } private: VMAddressSpace* fSpace; bool fLocked; }; class AddressSpaceWriteLocker : private AddressSpaceLockerBase { public: AddressSpaceWriteLocker(team_id team); AddressSpaceWriteLocker(VMAddressSpace* space, bool getNewReference); AddressSpaceWriteLocker(); ~AddressSpaceWriteLocker(); status_t SetTo(team_id team); void SetTo(VMAddressSpace* space, bool getNewReference); status_t SetFromArea(area_id areaID, VMArea*& area); status_t SetFromArea(team_id team, area_id areaID, bool allowKernel, VMArea*& area); status_t SetFromArea(team_id team, area_id areaID, VMArea*& area); bool IsLocked() const { return fLocked; } void Unlock(); void DegradeToReadLock(); void Unset(); VMAddressSpace* AddressSpace() const { return fSpace; } private: VMAddressSpace* fSpace; bool fLocked; bool fDegraded; }; class MultiAddressSpaceLocker : private AddressSpaceLockerBase { public: MultiAddressSpaceLocker(); ~MultiAddressSpaceLocker(); inline status_t AddTeam(team_id team, bool writeLock, VMAddressSpace** _space = NULL); inline status_t AddArea(area_id area, bool writeLock, VMAddressSpace** _space = NULL); inline status_t AddArea(VMArea* area, bool writeLock, VMAddressSpace** _space = NULL); status_t AddAreaCacheAndLock(area_id areaID, bool writeLockThisOne, bool writeLockOthers, VMArea*& _area, VMCache** _cache = NULL); status_t Lock(); void Unlock(); bool IsLocked() const { return fLocked; } void Unset(); private: struct lock_item { VMAddressSpace* space; bool write_lock; }; bool _ResizeIfNeeded(); int32 _IndexOfAddressSpace(VMAddressSpace* space) const; status_t _AddAddressSpace(VMAddressSpace* space, bool writeLock, VMAddressSpace** _space); static int _CompareItems(const void* _a, const void* _b); lock_item* fItems; int32 fCapacity; int32 fCount; bool fLocked; }; inline status_t MultiAddressSpaceLocker::AddTeam(team_id team, bool writeLock, VMAddressSpace** _space) { return _AddAddressSpace(VMAddressSpace::Get(team), writeLock, _space); } inline status_t MultiAddressSpaceLocker::AddArea(area_id area, bool writeLock, VMAddressSpace** _space) { return _AddAddressSpace(GetAddressSpaceByAreaID(area), writeLock, _space); } inline status_t MultiAddressSpaceLocker::AddArea(VMArea* area, bool writeLock, VMAddressSpace** _space) { area->address_space->Get(); return _AddAddressSpace(area->address_space, writeLock, _space); } #endif // VM_ADDRESS_SPACE_LOCKING_H