xref: /haiku/src/kits/app/ServerMemoryAllocator.cpp (revision 82a8a20999118b748396cf16a33c47c3b0c0222d)
1 /*
2  * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 /*!	Note, this class don't provide any locking whatsoever - you are
10 	supposed to have a BPrivate::AppServerLink object around which
11 	does the necessary locking.
12 	However, this is not enforced in the methods here, you have to
13 	take care for yourself!
14 */
15 
16 #include "ServerMemoryAllocator.h"
17 
18 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
19 #	include <syscalls.h>
20 #endif
21 
22 #include <new>
23 
24 
25 namespace BPrivate {
26 
27 struct area_mapping {
28 	area_id	server_area;
29 	area_id local_area;
30 	uint8*	local_base;
31 };
32 
33 
34 ServerMemoryAllocator::ServerMemoryAllocator()
35 	:
36 	fAreas(4)
37 {
38 }
39 
40 
41 ServerMemoryAllocator::~ServerMemoryAllocator()
42 {
43 	for (int32 i = fAreas.CountItems(); i-- > 0;) {
44 		area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
45 
46 		delete_area(mapping->local_area);
47 		delete mapping;
48 	}
49 }
50 
51 
52 status_t
53 ServerMemoryAllocator::InitCheck()
54 {
55 	return B_OK;
56 }
57 
58 
59 status_t
60 ServerMemoryAllocator::AddArea(area_id serverArea, area_id& _area, uint8*& _base,
61 	bool readOnly)
62 {
63 	area_mapping* mapping = new (std::nothrow) area_mapping;
64 	if (mapping == NULL || !fAreas.AddItem(mapping)) {
65 		delete mapping;
66 		return B_NO_MEMORY;
67 	}
68 
69 	status_t status = B_ERROR;
70 	uint32 addressSpec = B_ANY_ADDRESS;
71 	void* base;
72 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
73 	if (!readOnly) {
74 		// reserve 128 MB of space for the area
75 		base = (void*)0x60000000;
76 		status = _kern_reserve_address_range((addr_t*)&base, B_BASE_ADDRESS,
77 			128 * 1024 * 1024);
78 		addressSpec = status == B_OK ? B_EXACT_ADDRESS : B_BASE_ADDRESS;
79 	}
80 #endif
81 
82 	mapping->local_area = clone_area(readOnly
83 			? "server read-only memory" : "server_memory",
84 		&base, addressSpec,
85 		B_READ_AREA | (readOnly ? 0 : B_WRITE_AREA), serverArea);
86 	if (mapping->local_area < B_OK) {
87 		status = mapping->local_area;
88 
89 		fAreas.RemoveItem(mapping);
90 		delete mapping;
91 
92 		return status;
93 	}
94 
95 	mapping->server_area = serverArea;
96 	mapping->local_base = (uint8*)base;
97 
98 	_area = mapping->local_area;
99 	_base = mapping->local_base;
100 
101 	return B_OK;
102 }
103 
104 
105 void
106 ServerMemoryAllocator::RemoveArea(area_id serverArea)
107 {
108 	for (int32 i = fAreas.CountItems(); i-- > 0;) {
109 		area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
110 
111 		if (mapping->server_area == serverArea) {
112 			// we found the area we should remove
113 			delete_area(mapping->local_area);
114 			delete mapping;
115 			break;
116 		}
117 	}
118 }
119 
120 
121 status_t
122 ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area,
123 	uint8*& _base)
124 {
125 	for (int32 i = fAreas.CountItems(); i-- > 0;) {
126 		area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
127 
128 		if (mapping->server_area == serverArea) {
129 			_area = mapping->local_area;
130 			_base = mapping->local_base;
131 			return B_OK;
132 		}
133 	}
134 
135 	return B_ERROR;
136 }
137 
138 }	// namespace BPrivate
139