xref: /haiku/src/system/kernel/vm/VMAddressSpaceLocking.h (revision 71452e98334eaac603bf542d159e24788a46bebb)
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 
15 struct VMAddressSpace;
16 struct VMArea;
17 struct VMCache;
18 
19 
20 class AddressSpaceLockerBase {
21 public:
22 	static	VMAddressSpace*		GetAddressSpaceByAreaID(area_id id);
23 };
24 
25 
26 class AddressSpaceReadLocker : private AddressSpaceLockerBase {
27 public:
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 
47 private:
48 			VMAddressSpace*		fSpace;
49 			bool				fLocked;
50 };
51 
52 
53 class AddressSpaceWriteLocker : private AddressSpaceLockerBase {
54 public:
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 
78 private:
79 			VMAddressSpace*		fSpace;
80 			bool				fLocked;
81 			bool				fDegraded;
82 };
83 
84 
85 class MultiAddressSpaceLocker : private AddressSpaceLockerBase {
86 public:
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 
107 private:
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 
128 inline status_t
129 MultiAddressSpaceLocker::AddTeam(team_id team, bool writeLock,
130 	VMAddressSpace** _space)
131 {
132 	return _AddAddressSpace(VMAddressSpace::Get(team), writeLock, _space);
133 }
134 
135 
136 inline status_t
137 MultiAddressSpaceLocker::AddArea(area_id area, bool writeLock,
138 	VMAddressSpace** _space)
139 {
140 	return _AddAddressSpace(GetAddressSpaceByAreaID(area), writeLock, _space);
141 }
142 
143 
144 inline status_t
145 MultiAddressSpaceLocker::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