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