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 27 static const size_t kReservedSize = 128 * 1024 * 1024; 28 static const size_t kReserveMaxSize = 32 * 1024 * 1024; 29 30 31 namespace BPrivate { 32 33 34 struct area_mapping { 35 area_id server_area; 36 area_id local_area; 37 uint8* local_base; 38 }; 39 40 41 ServerMemoryAllocator::ServerMemoryAllocator() 42 : 43 fAreas(4) 44 { 45 } 46 47 48 ServerMemoryAllocator::~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 59 status_t 60 ServerMemoryAllocator::InitCheck() 61 { 62 return B_OK; 63 } 64 65 66 status_t 67 ServerMemoryAllocator::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 114 void 115 ServerMemoryAllocator::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 131 status_t 132 ServerMemoryAllocator::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