1 /* 2 * Copyright 2011, Rene Gollent, rene@gollent.com. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "TeamMemoryBlockManager.h" 8 9 #include <new> 10 11 #include <AutoDeleter.h> 12 #include <AutoLocker.h> 13 14 #include "TeamMemoryBlock.h" 15 16 17 struct TeamMemoryBlockManager::Key { 18 target_addr_t address; 19 20 Key(target_addr_t address) 21 : 22 address(address) 23 { 24 } 25 26 uint32 HashValue() const 27 { 28 return (uint32)address; 29 } 30 31 bool operator==(const Key& other) const 32 { 33 return address == other.address; 34 } 35 }; 36 37 38 struct TeamMemoryBlockManager::MemoryBlockEntry : Key { 39 TeamMemoryBlock* block; 40 MemoryBlockEntry* next; 41 42 MemoryBlockEntry(TeamMemoryBlock* block) 43 : 44 Key(block->BaseAddress()), 45 block(block) 46 { 47 } 48 49 ~MemoryBlockEntry() 50 { 51 } 52 }; 53 54 55 struct TeamMemoryBlockManager::MemoryBlockHashDefinition { 56 typedef Key KeyType; 57 typedef MemoryBlockEntry ValueType; 58 59 size_t HashKey(const Key& key) const 60 { 61 return key.HashValue(); 62 } 63 64 size_t Hash(const MemoryBlockEntry* value) const 65 { 66 return value->HashValue(); 67 } 68 69 bool Compare(const Key& key, const MemoryBlockEntry* value) const 70 { 71 return key == *value; 72 } 73 74 MemoryBlockEntry*& GetLink(MemoryBlockEntry* value) const 75 { 76 return value->next; 77 } 78 }; 79 80 81 TeamMemoryBlockManager::TeamMemoryBlockManager() 82 : 83 fActiveBlocks(NULL), 84 fDeadBlocks(NULL) 85 { 86 } 87 88 89 TeamMemoryBlockManager::~TeamMemoryBlockManager() 90 { 91 _Cleanup(); 92 } 93 94 95 status_t 96 TeamMemoryBlockManager::Init() 97 { 98 status_t result = fLock.InitCheck(); 99 if (result != B_OK) 100 return result; 101 102 fActiveBlocks = new(std::nothrow) MemoryBlockTable(); 103 if (fActiveBlocks == NULL) 104 return B_NO_MEMORY; 105 ObjectDeleter<MemoryBlockTable> activeDeleter(fActiveBlocks); 106 result = fActiveBlocks->Init(); 107 if (result != B_OK) 108 return result; 109 110 fDeadBlocks = new(std::nothrow) DeadBlockTable(); 111 if (fDeadBlocks == NULL) 112 return B_NO_MEMORY; 113 114 activeDeleter.Detach(); 115 116 return B_OK; 117 } 118 119 120 TeamMemoryBlock* 121 TeamMemoryBlockManager::GetMemoryBlock(target_addr_t address) 122 { 123 AutoLocker<BLocker> lock(fLock); 124 125 address &= ~(B_PAGE_SIZE - 1); 126 MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); 127 if (entry != NULL) { 128 if (entry->block->AcquireReference() != 0) 129 return entry->block; 130 131 // this block already had its last reference released, 132 // move it to the dead list and create a new one instead. 133 _MarkDeadBlock(address); 134 } 135 136 TeamMemoryBlockOwner* owner = new(std::nothrow) TeamMemoryBlockOwner(this); 137 if (owner == NULL) 138 return NULL; 139 ObjectDeleter<TeamMemoryBlockOwner> ownerDeleter(owner); 140 141 TeamMemoryBlock* block = new(std::nothrow) TeamMemoryBlock(address, 142 owner); 143 if (block == NULL) 144 return NULL; 145 ObjectDeleter<TeamMemoryBlock> blockDeleter(block); 146 147 entry = new(std::nothrow) MemoryBlockEntry(block); 148 if (entry == NULL) 149 return NULL; 150 151 ownerDeleter.Detach(); 152 blockDeleter.Detach(); 153 fActiveBlocks->Insert(entry); 154 155 return entry->block; 156 } 157 158 159 void 160 TeamMemoryBlockManager::_Cleanup() 161 { 162 if (fActiveBlocks != NULL) { 163 MemoryBlockEntry* entry = fActiveBlocks->Clear(true); 164 165 while (entry != NULL) { 166 MemoryBlockEntry* next = entry->next; 167 delete entry; 168 entry = next; 169 } 170 171 delete fActiveBlocks; 172 fActiveBlocks = NULL; 173 } 174 } 175 176 177 void 178 TeamMemoryBlockManager::_MarkDeadBlock(target_addr_t address) 179 { 180 MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); 181 if (entry != NULL) { 182 fActiveBlocks->Remove(entry); 183 fDeadBlocks->Insert(entry->block); 184 delete entry; 185 } 186 } 187 188 189 void 190 TeamMemoryBlockManager::_RemoveBlock(target_addr_t address) 191 { 192 AutoLocker<BLocker> lock(fLock); 193 MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); 194 if (entry != NULL) { 195 fActiveBlocks->Remove(entry); 196 delete entry; 197 return; 198 } 199 200 DeadBlockTable::Iterator iterator = fDeadBlocks->GetIterator(); 201 while (iterator.HasNext()) { 202 TeamMemoryBlock* block = iterator.Next(); 203 if (block->BaseAddress() == address) { 204 fDeadBlocks->Remove(block); 205 break; 206 } 207 } 208 } 209 210 211 TeamMemoryBlockOwner::TeamMemoryBlockOwner(TeamMemoryBlockManager* manager) 212 : 213 fBlockManager(manager) 214 { 215 } 216 217 218 TeamMemoryBlockOwner::~TeamMemoryBlockOwner() 219 { 220 } 221 222 223 void 224 TeamMemoryBlockOwner::RemoveBlock(TeamMemoryBlock* block) 225 { 226 fBlockManager->_RemoveBlock(block->BaseAddress()); 227 } 228