xref: /haiku/headers/private/kernel/vm/VMArea.h (revision 9a6a20d4689307142a7ed26a1437ba47e244e73f)
1 /*
2  * Copyright 2009-2010, 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  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 #ifndef _KERNEL_VM_VM_AREA_H
10 #define _KERNEL_VM_VM_AREA_H
11 
12 
13 #include <vm_defs.h>
14 
15 #include <lock.h>
16 #include <util/DoublyLinkedList.h>
17 #include <util/SinglyLinkedList.h>
18 #include <util/AVLTree.h>
19 #include <vm/vm_types.h>
20 
21 
22 struct VMAddressSpace;
23 struct VMCache;
24 struct VMKernelAddressSpace;
25 struct VMUserAddressSpace;
26 
27 
28 struct VMAreaUnwiredWaiter
29 	: public DoublyLinkedListLinkImpl<VMAreaUnwiredWaiter> {
30 	VMArea*					area;
31 	addr_t					base;
32 	size_t					size;
33 	ConditionVariable		condition;
34 	ConditionVariableEntry	waitEntry;
35 };
36 
37 typedef DoublyLinkedList<VMAreaUnwiredWaiter> VMAreaUnwiredWaiterList;
38 
39 
40 struct VMAreaWiredRange : SinglyLinkedListLinkImpl<VMAreaWiredRange> {
41 	VMArea*					area;
42 	addr_t					base;
43 	size_t					size;
44 	bool					writable;
45 	bool					implicit;	// range created automatically
46 	VMAreaUnwiredWaiterList	waiters;
47 
48 	VMAreaWiredRange()
49 	{
50 	}
51 
52 	VMAreaWiredRange(addr_t base, size_t size, bool writable, bool implicit)
53 		:
54 		area(NULL),
55 		base(base),
56 		size(size),
57 		writable(writable),
58 		implicit(implicit)
59 	{
60 	}
61 
62 	void SetTo(addr_t base, size_t size, bool writable, bool implicit)
63 	{
64 		this->area = NULL;
65 		this->base = base;
66 		this->size = size;
67 		this->writable = writable;
68 		this->implicit = implicit;
69 	}
70 
71 	bool IntersectsWith(addr_t base, size_t size) const
72 	{
73 		return this->base + this->size - 1 >= base
74 			&& base + size - 1 >= this->base;
75 	}
76 };
77 
78 typedef SinglyLinkedList<VMAreaWiredRange> VMAreaWiredRangeList;
79 
80 
81 struct VMPageWiringInfo {
82 	VMAreaWiredRange	range;
83 	phys_addr_t			physicalAddress;
84 							// the actual physical address corresponding to
85 							// the virtual address passed to vm_wire_page()
86 							// (i.e. with in-page offset)
87 	vm_page*			page;
88 };
89 
90 
91 struct VMAreasTreeNode {
92 	AVLTreeNode tree_node;
93 };
94 
95 
96 struct VMArea : private VMAreasTreeNode {
97 public:
98 	enum {
99 		// AddWaiterIfWired() flags
100 		IGNORE_WRITE_WIRED_RANGES	= 0x01,	// ignore existing ranges that
101 											// wire for writing
102 	};
103 
104 public:
105 	area_id					id;
106 	char					name[B_OS_NAME_LENGTH];
107 	uint32					protection;
108 	uint32					protection_max;
109 	uint16					wiring;
110 
111 private:
112 	uint16					memory_type;	// >> shifted by MEMORY_TYPE_SHIFT
113 
114 public:
115 	VMCache*				cache;
116 	vint32					no_cache_change;
117 	off_t					cache_offset;
118 	uint32					cache_type;
119 	VMAreaMappings			mappings;
120 	uint8*					page_protections;
121 
122 	struct VMAddressSpace*	address_space;
123 	struct VMArea*			cache_next;
124 	struct VMArea*			cache_prev;
125 
126 			addr_t				Base() const	{ return fBase; }
127 			size_t				Size() const	{ return fSize; }
128 
129 	inline	uint32				MemoryType() const;
130 	inline	void				SetMemoryType(uint32 memoryType);
131 
132 			bool				ContainsAddress(addr_t address) const
133 									{ return address >= fBase
134 										&& address <= fBase + (fSize - 1); }
135 
136 			bool				IsWired() const
137 									{ return !fWiredRanges.IsEmpty(); }
138 			bool				IsWired(addr_t base, size_t size) const;
139 
140 			void				Wire(VMAreaWiredRange* range);
141 			void				Unwire(VMAreaWiredRange* range);
142 			VMAreaWiredRange*	Unwire(addr_t base, size_t size, bool writable);
143 
144 			bool				AddWaiterIfWired(VMAreaUnwiredWaiter* waiter);
145 			bool				AddWaiterIfWired(VMAreaUnwiredWaiter* waiter,
146 									addr_t base, size_t size, uint32 flags = 0);
147 
148 protected:
149 								VMArea(VMAddressSpace* addressSpace,
150 									uint32 wiring, uint32 protection);
151 								~VMArea();
152 
153 			status_t			Init(const char* name, uint32 allocationFlags);
154 
155 protected:
156 			friend struct VMAreasTreeDefinition;
157 			friend struct VMKernelAddressSpace;
158 			friend struct VMUserAddressSpace;
159 
160 protected:
161 			void				SetBase(addr_t base)	{ fBase = base; }
162 			void				SetSize(size_t size)	{ fSize = size; }
163 
164 protected:
165 			addr_t				fBase;
166 			size_t				fSize;
167 			VMAreaWiredRangeList fWiredRanges;
168 };
169 
170 
171 struct VMAreasTreeDefinition {
172 	typedef area_id		Key;
173 	typedef VMArea		Value;
174 
175 	AVLTreeNode* GetAVLTreeNode(VMArea* value) const
176 	{
177 		return &value->tree_node;
178 	}
179 
180 	VMArea* GetValue(AVLTreeNode* node) const
181 	{
182 		const addr_t vmTreeNodeAddr = (addr_t)node
183 			- offsetof(VMAreasTreeNode, tree_node);
184 		VMAreasTreeNode* vmTreeNode =
185 			reinterpret_cast<VMAreasTreeNode*>(vmTreeNodeAddr);
186 		return static_cast<VMArea*>(vmTreeNode);
187 	}
188 
189 	int Compare(area_id key, const VMArea* value) const
190 	{
191 		const area_id valueId = value->id;
192 		if (valueId == key)
193 			return 0;
194 		return key < valueId ? -1 : 1;
195 	}
196 
197 	int Compare(const VMArea* a, const VMArea* b) const
198 	{
199 		return Compare(a->id, b);
200 	}
201 };
202 
203 typedef AVLTree<VMAreasTreeDefinition> VMAreasTree;
204 
205 
206 struct VMAreas {
207 	static	status_t			Init();
208 
209 	static	status_t			ReadLock()
210 									{ return rw_lock_read_lock(&sLock); }
211 	static	void				ReadUnlock()
212 									{ rw_lock_read_unlock(&sLock); }
213 	static	status_t			WriteLock()
214 									{ return rw_lock_write_lock(&sLock); }
215 	static	void				WriteUnlock()
216 									{ rw_lock_write_unlock(&sLock); }
217 
218 	static	VMArea*				LookupLocked(area_id id)
219 									{ return sTree.Find(id); }
220 	static	VMArea*				Lookup(area_id id);
221 	static	area_id				Find(const char* name);
222 	static	status_t			Insert(VMArea* area);
223 	static	void				Remove(VMArea* area);
224 
225 	static	VMAreasTree::Iterator GetIterator()
226 									{ return sTree.GetIterator(); }
227 
228 private:
229 	static	rw_lock				sLock;
230 	static	VMAreasTree			sTree;
231 };
232 
233 
234 uint32
235 VMArea::MemoryType() const
236 {
237 	return (uint32)memory_type << MEMORY_TYPE_SHIFT;
238 }
239 
240 
241 void
242 VMArea::SetMemoryType(uint32 memoryType)
243 {
244 	memory_type = memoryType >> MEMORY_TYPE_SHIFT;
245 }
246 
247 
248 #endif	// _KERNEL_VM_VM_AREA_H
249