VMArea.h revision 30c9d3c0
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
22struct VMAddressSpace;
23struct VMCache;
24struct VMKernelAddressSpace;
25struct VMUserAddressSpace;
26
27
28struct VMAreaUnwiredWaiter
29	: public DoublyLinkedListLinkImpl<VMAreaUnwiredWaiter> {
30	VMArea*					area;
31	addr_t					base;
32	size_t					size;
33	ConditionVariable		condition;
34	ConditionVariableEntry	waitEntry;
35};
36
37typedef DoublyLinkedList<VMAreaUnwiredWaiter> VMAreaUnwiredWaiterList;
38
39
40struct 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
78typedef SinglyLinkedList<VMAreaWiredRange> VMAreaWiredRangeList;
79
80
81struct 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
91struct VMArea {
92public:
93	enum {
94		// AddWaiterIfWired() flags
95		IGNORE_WRITE_WIRED_RANGES	= 0x01,	// ignore existing ranges that
96											// wire for writing
97	};
98
99public:
100	char*					name;
101	area_id					id;
102	uint32					protection;
103	uint16					wiring;
104
105private:
106	uint16					memory_type;	// >> shifted by MEMORY_TYPE_SHIFT
107
108public:
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
143protected:
144								VMArea(VMAddressSpace* addressSpace,
145									uint32 wiring, uint32 protection);
146								~VMArea();
147
148			status_t			Init(const char* name, uint32 allocationFlags);
149
150protected:
151			friend struct VMAddressSpace;
152			friend struct VMKernelAddressSpace;
153			friend struct VMUserAddressSpace;
154
155protected:
156			void				SetBase(addr_t base)	{ fBase = base; }
157			void				SetSize(size_t size)	{ fSize = size; }
158
159protected:
160			addr_t				fBase;
161			size_t				fSize;
162			VMAreaWiredRangeList fWiredRanges;
163};
164
165
166struct 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
191typedef BOpenHashTable<VMAreaHashDefinition> VMAreaHashTable;
192
193
194struct 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
216private:
217	static	rw_lock				sLock;
218	static	VMAreaHashTable		sTable;
219};
220
221
222uint32
223VMArea::MemoryType() const
224{
225	return (uint32)memory_type << MEMORY_TYPE_SHIFT;
226}
227
228
229void
230VMArea::SetMemoryType(uint32 memoryType)
231{
232	memory_type = memoryType >> MEMORY_TYPE_SHIFT;
233}
234
235
236#endif	// _KERNEL_VM_VM_AREA_H
237