xref: /haiku/headers/private/kernel/vm/VMArea.h (revision b5a859ad6285b14769a5ede7b81e4261044faf7e)
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/OpenHashTable.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 VMArea {
92 public:
93 	enum {
94 		// AddWaiterIfWired() flags
95 		IGNORE_WRITE_WIRED_RANGES	= 0x01,	// ignore existing ranges that
96 											// wire for writing
97 	};
98 
99 public:
100 	area_id					id;
101 	char					name[B_OS_NAME_LENGTH];
102 	uint32					protection;
103 	uint32					protection_max;
104 	uint16					wiring;
105 
106 private:
107 	uint16					memory_type;	// >> shifted by MEMORY_TYPE_SHIFT
108 
109 public:
110 	VMCache*				cache;
111 	vint32					no_cache_change;
112 	off_t					cache_offset;
113 	uint32					cache_type;
114 	VMAreaMappings			mappings;
115 	uint8*					page_protections;
116 
117 	struct VMAddressSpace*	address_space;
118 	struct VMArea*			cache_next;
119 	struct VMArea*			cache_prev;
120 	struct VMArea*			hash_next;
121 
122 			addr_t				Base() const	{ return fBase; }
123 			size_t				Size() const	{ return fSize; }
124 
125 	inline	uint32				MemoryType() const;
126 	inline	void				SetMemoryType(uint32 memoryType);
127 
128 			bool				ContainsAddress(addr_t address) const
129 									{ return address >= fBase
130 										&& address <= fBase + (fSize - 1); }
131 
132 			bool				IsWired() const
133 									{ return !fWiredRanges.IsEmpty(); }
134 			bool				IsWired(addr_t base, size_t size) const;
135 
136 			void				Wire(VMAreaWiredRange* range);
137 			void				Unwire(VMAreaWiredRange* range);
138 			VMAreaWiredRange*	Unwire(addr_t base, size_t size, bool writable);
139 
140 			bool				AddWaiterIfWired(VMAreaUnwiredWaiter* waiter);
141 			bool				AddWaiterIfWired(VMAreaUnwiredWaiter* waiter,
142 									addr_t base, size_t size, uint32 flags = 0);
143 
144 protected:
145 								VMArea(VMAddressSpace* addressSpace,
146 									uint32 wiring, uint32 protection);
147 								~VMArea();
148 
149 			status_t			Init(const char* name, uint32 allocationFlags);
150 
151 protected:
152 			friend struct VMAddressSpace;
153 			friend struct VMKernelAddressSpace;
154 			friend struct VMUserAddressSpace;
155 
156 protected:
157 			void				SetBase(addr_t base)	{ fBase = base; }
158 			void				SetSize(size_t size)	{ fSize = size; }
159 
160 protected:
161 			addr_t				fBase;
162 			size_t				fSize;
163 			VMAreaWiredRangeList fWiredRanges;
164 };
165 
166 
167 struct VMAreaHashDefinition {
168 	typedef area_id		KeyType;
169 	typedef VMArea		ValueType;
170 
171 	size_t HashKey(area_id key) const
172 	{
173 		return key;
174 	}
175 
176 	size_t Hash(const VMArea* value) const
177 	{
178 		return HashKey(value->id);
179 	}
180 
181 	bool Compare(area_id key, const VMArea* value) const
182 	{
183 		return value->id == key;
184 	}
185 
186 	VMArea*& GetLink(VMArea* value) const
187 	{
188 		return value->hash_next;
189 	}
190 };
191 
192 typedef BOpenHashTable<VMAreaHashDefinition> VMAreaHashTable;
193 
194 
195 struct VMAreaHash {
196 	static	status_t			Init();
197 
198 	static	status_t			ReadLock()
199 									{ return rw_lock_read_lock(&sLock); }
200 	static	void				ReadUnlock()
201 									{ rw_lock_read_unlock(&sLock); }
202 	static	status_t			WriteLock()
203 									{ return rw_lock_write_lock(&sLock); }
204 	static	void				WriteUnlock()
205 									{ rw_lock_write_unlock(&sLock); }
206 
207 	static	VMArea*				LookupLocked(area_id id)
208 									{ return sTable.Lookup(id); }
209 	static	VMArea*				Lookup(area_id id);
210 	static	area_id				Find(const char* name);
211 	static	void				Insert(VMArea* area);
212 	static	void				Remove(VMArea* area);
213 
214 	static	VMAreaHashTable::Iterator GetIterator()
215 									{ return sTable.GetIterator(); }
216 
217 private:
218 	static	rw_lock				sLock;
219 	static	VMAreaHashTable		sTable;
220 };
221 
222 
223 uint32
224 VMArea::MemoryType() const
225 {
226 	return (uint32)memory_type << MEMORY_TYPE_SHIFT;
227 }
228 
229 
230 void
231 VMArea::SetMemoryType(uint32 memoryType)
232 {
233 	memory_type = memoryType >> MEMORY_TYPE_SHIFT;
234 }
235 
236 
237 #endif	// _KERNEL_VM_VM_AREA_H
238