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_READ_AREA | (readOnly ? 0 : B_WRITE_AREA), serverArea); 94 if (mapping->local_area < B_OK) { 95 status = mapping->local_area; 96 97 fAreas.RemoveItem(mapping); 98 delete mapping; 99 100 return status; 101 } 102 103 mapping->server_area = serverArea; 104 mapping->local_base = (uint8*)base; 105 106 _area = mapping->local_area; 107 _base = mapping->local_base; 108 109 return B_OK; 110 } 111 112 113 void 114 ServerMemoryAllocator::RemoveArea(area_id serverArea) 115 { 116 for (int32 i = fAreas.CountItems(); i-- > 0;) { 117 area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i); 118 119 if (mapping->server_area == serverArea) { 120 // we found the area we should remove 121 delete_area(mapping->local_area); 122 delete mapping; 123 fAreas.RemoveItem(i); 124 break; 125 } 126 } 127 } 128 129 130 status_t 131 ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area, 132 uint8*& _base) 133 { 134 // TODO: why not use a map? 135 for (int32 i = fAreas.CountItems(); i-- > 0;) { 136 area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i); 137 138 if (mapping->server_area == serverArea) { 139 _area = mapping->local_area; 140 _base = mapping->local_base; 141 return B_OK; 142 } 143 } 144 145 return B_ERROR; 146 } 147 148 149 } // namespace BPrivate 150