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