1/* 2 * Copyright 2006-2012, 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 18#include "ServerMemoryAllocator.h" 19 20#include <new> 21 22#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 23# include <syscalls.h> 24#endif 25 26 27static const size_t kReservedSize = 128 * 1024 * 1024; 28static const size_t kReserveMaxSize = 32 * 1024 * 1024; 29 30 31namespace BPrivate { 32 33 34struct area_mapping { 35 area_id server_area; 36 area_id local_area; 37 uint8* local_base; 38}; 39 40 41ServerMemoryAllocator::ServerMemoryAllocator() 42 : 43 fAreas(4) 44{ 45} 46 47 48ServerMemoryAllocator::~ServerMemoryAllocator() 49{ 50 for (int32 i = fAreas.CountItems(); i-- > 0;) { 51 area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i); 52 53 delete_area(mapping->local_area); 54 delete mapping; 55 } 56} 57 58 59status_t 60ServerMemoryAllocator::InitCheck() 61{ 62 return B_OK; 63} 64 65 66status_t 67ServerMemoryAllocator::AddArea(area_id serverArea, area_id& _area, 68 uint8*& _base, size_t size, bool readOnly) 69{ 70 area_mapping* mapping = new (std::nothrow) area_mapping; 71 if (mapping == NULL || !fAreas.AddItem(mapping)) { 72 delete mapping; 73 return B_NO_MEMORY; 74 } 75 76 status_t status = B_ERROR; 77 uint32 addressSpec = B_ANY_ADDRESS; 78 void* base; 79#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 80 if (!readOnly && size < kReserveMaxSize) { 81 // Reserve 128 MB of space for the area, but only if the area 82 // is smaller than 32 MB (else the address space waste would 83 // likely to be too large) 84 base = (void*)0x60000000; 85 status = _kern_reserve_address_range((addr_t*)&base, B_BASE_ADDRESS, 86 kReservedSize); 87 addressSpec = status == B_OK ? B_EXACT_ADDRESS : B_BASE_ADDRESS; 88 } 89#endif 90 91 mapping->local_area = clone_area(readOnly 92 ? "server read-only memory" : "server_memory", &base, addressSpec, 93 B_CLONEABLE_AREA | B_READ_AREA | (readOnly ? 0 : B_WRITE_AREA), 94 serverArea); 95 if (mapping->local_area < B_OK) { 96 status = mapping->local_area; 97 98 fAreas.RemoveItem(mapping); 99 delete mapping; 100 101 return status; 102 } 103 104 mapping->server_area = serverArea; 105 mapping->local_base = (uint8*)base; 106 107 _area = mapping->local_area; 108 _base = mapping->local_base; 109 110 return B_OK; 111} 112 113 114void 115ServerMemoryAllocator::RemoveArea(area_id serverArea) 116{ 117 for (int32 i = fAreas.CountItems(); i-- > 0;) { 118 area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i); 119 120 if (mapping->server_area == serverArea) { 121 // we found the area we should remove 122 delete_area(mapping->local_area); 123 delete mapping; 124 fAreas.RemoveItem(i); 125 break; 126 } 127 } 128} 129 130 131status_t 132ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area, 133 uint8*& _base) 134{ 135 // TODO: why not use a map? 136 for (int32 i = fAreas.CountItems(); i-- > 0;) { 137 area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i); 138 139 if (mapping->server_area == serverArea) { 140 _area = mapping->local_area; 141 _base = mapping->local_base; 142 return B_OK; 143 } 144 } 145 146 return B_ERROR; 147} 148 149 150} // namespace BPrivate 151