xref: /haiku/src/system/kernel/vm/VMArea.cpp (revision 9563f44bfd75799f67201067483694e82b5779b9)
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  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 
11 #include <vm/VMArea.h>
12 
13 #include <new>
14 
15 #include <heap.h>
16 
17 
18 #define AREA_HASH_TABLE_SIZE 1024
19 
20 
21 rw_lock VMAreaHash::sLock = RW_LOCK_INITIALIZER("area hash");
22 VMAreaHashTable VMAreaHash::sTable;
23 static area_id sNextAreaID = 1;
24 
25 
26 // #pragma mark - VMArea
27 
28 VMArea::VMArea(VMAddressSpace* addressSpace, uint32 wiring, uint32 protection)
29 	:
30 	name(NULL),
31 	protection(protection),
32 	wiring(wiring),
33 	memory_type(0),
34 	cache(NULL),
35 	no_cache_change(0),
36 	cache_offset(0),
37 	cache_type(0),
38 	page_protections(NULL),
39 	address_space(addressSpace),
40 	cache_next(NULL),
41 	cache_prev(NULL),
42 	hash_next(NULL)
43 {
44 	new (&mappings) VMAreaMappings;
45 }
46 
47 
48 VMArea::~VMArea()
49 {
50 	free(page_protections);
51 	free(name);
52 }
53 
54 
55 status_t
56 VMArea::Init(const char* name)
57 {
58 	// restrict the area name to B_OS_NAME_LENGTH
59 	size_t length = strlen(name) + 1;
60 	if (length > B_OS_NAME_LENGTH)
61 		length = B_OS_NAME_LENGTH;
62 
63 	// clone the name
64 	this->name = (char*)malloc_nogrow(length);
65 	if (this->name == NULL)
66 		return B_NO_MEMORY;
67 	strlcpy(this->name, name, length);
68 
69 	id = atomic_add(&sNextAreaID, 1);
70 	return B_OK;
71 }
72 
73 
74 // #pragma mark - VMAreaHash
75 
76 
77 /*static*/ status_t
78 VMAreaHash::Init()
79 {
80 	return sTable.Init(AREA_HASH_TABLE_SIZE);
81 }
82 
83 
84 /*static*/ VMArea*
85 VMAreaHash::Lookup(area_id id)
86 {
87 	ReadLock();
88 	VMArea* area = LookupLocked(id);
89 	ReadUnlock();
90 	return area;
91 }
92 
93 
94 /*static*/ area_id
95 VMAreaHash::Find(const char* name)
96 {
97 	ReadLock();
98 
99 	area_id id = B_NAME_NOT_FOUND;
100 
101 	// TODO: Iterating through the whole table can be very slow and the whole
102 	// time we're holding the lock! Use a second hash table!
103 
104 	for (VMAreaHashTable::Iterator it = sTable.GetIterator();
105 			VMArea* area = it.Next();) {
106 		if (strcmp(area->name, name) == 0) {
107 			id = area->id;
108 			break;
109 		}
110 	}
111 
112 	ReadUnlock();
113 
114 	return id;
115 }
116 
117 
118 /*static*/ void
119 VMAreaHash::Insert(VMArea* area)
120 {
121 	WriteLock();
122 	sTable.Insert(area);
123 	WriteUnlock();
124 }
125 
126 
127 /*static*/ void
128 VMAreaHash::Remove(VMArea* area)
129 {
130 	WriteLock();
131 	sTable.Remove(area);
132 	WriteUnlock();
133 }
134