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