1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2002-2009, Axel D��rfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
5 */
6#ifndef VM_ADDRESS_SPACE_LOCKING_H
7#define VM_ADDRESS_SPACE_LOCKING_H
8
9
10#include <OS.h>
11
12#include <vm/VMAddressSpace.h>
13
14
15struct VMAddressSpace;
16struct VMArea;
17struct VMCache;
18
19
20class AddressSpaceLockerBase {
21public:
22	static	VMAddressSpace*		GetAddressSpaceByAreaID(area_id id);
23};
24
25
26class AddressSpaceReadLocker : private AddressSpaceLockerBase {
27public:
28								AddressSpaceReadLocker(team_id team);
29								AddressSpaceReadLocker(VMAddressSpace* space,
30									bool getNewReference);
31								AddressSpaceReadLocker();
32								~AddressSpaceReadLocker();
33
34			status_t			SetTo(team_id team);
35			void				SetTo(VMAddressSpace* space,
36									bool getNewReference);
37			status_t			SetFromArea(area_id areaID, VMArea*& area);
38
39			bool				IsLocked() const { return fLocked; }
40			bool				Lock();
41			void				Unlock();
42
43			void				Unset();
44
45			VMAddressSpace*		AddressSpace() const { return fSpace; }
46
47private:
48			VMAddressSpace*		fSpace;
49			bool				fLocked;
50};
51
52
53class AddressSpaceWriteLocker : private AddressSpaceLockerBase {
54public:
55								AddressSpaceWriteLocker(team_id team);
56								AddressSpaceWriteLocker(VMAddressSpace* space,
57									bool getNewReference);
58								AddressSpaceWriteLocker();
59								~AddressSpaceWriteLocker();
60
61			status_t			SetTo(team_id team);
62			void				SetTo(VMAddressSpace* space,
63									bool getNewReference);
64			status_t			SetFromArea(area_id areaID, VMArea*& area);
65			status_t			SetFromArea(team_id team, area_id areaID,
66									bool allowKernel, VMArea*& area);
67			status_t			SetFromArea(team_id team, area_id areaID,
68									VMArea*& area);
69
70			bool				IsLocked() const { return fLocked; }
71			void				Unlock();
72
73			void				DegradeToReadLock();
74			void				Unset();
75
76			VMAddressSpace*		AddressSpace() const { return fSpace; }
77
78private:
79			VMAddressSpace*		fSpace;
80			bool				fLocked;
81			bool				fDegraded;
82};
83
84
85class MultiAddressSpaceLocker : private AddressSpaceLockerBase {
86public:
87								MultiAddressSpaceLocker();
88								~MultiAddressSpaceLocker();
89
90	inline	status_t			AddTeam(team_id team, bool writeLock,
91									VMAddressSpace** _space = NULL);
92	inline	status_t			AddArea(area_id area, bool writeLock,
93									VMAddressSpace** _space = NULL);
94	inline	status_t			AddArea(VMArea* area, bool writeLock,
95									VMAddressSpace** _space = NULL);
96
97			status_t			AddAreaCacheAndLock(area_id areaID,
98									bool writeLockThisOne, bool writeLockOthers,
99									VMArea*& _area, VMCache** _cache = NULL);
100
101			status_t			Lock();
102			void				Unlock();
103			bool				IsLocked() const { return fLocked; }
104
105			void				Unset();
106
107private:
108			struct lock_item {
109				VMAddressSpace*	space;
110				bool			write_lock;
111			};
112
113			bool				_ResizeIfNeeded();
114			int32				_IndexOfAddressSpace(VMAddressSpace* space)
115									const;
116			status_t			_AddAddressSpace(VMAddressSpace* space,
117									bool writeLock, VMAddressSpace** _space);
118
119	static	int					_CompareItems(const void* _a, const void* _b);
120
121			lock_item*			fItems;
122			int32				fCapacity;
123			int32				fCount;
124			bool				fLocked;
125};
126
127
128inline status_t
129MultiAddressSpaceLocker::AddTeam(team_id team, bool writeLock,
130	VMAddressSpace** _space)
131{
132	return _AddAddressSpace(VMAddressSpace::Get(team), writeLock, _space);
133}
134
135
136inline status_t
137MultiAddressSpaceLocker::AddArea(area_id area, bool writeLock,
138	VMAddressSpace** _space)
139{
140	return _AddAddressSpace(GetAddressSpaceByAreaID(area), writeLock, _space);
141}
142
143
144inline status_t
145MultiAddressSpaceLocker::AddArea(VMArea* area, bool writeLock,
146	VMAddressSpace** _space)
147{
148	area->address_space->Get();
149	return _AddAddressSpace(area->address_space, writeLock, _space);
150}
151
152
153#endif	// VM_ADDRESS_SPACE_LOCKING_H
154