1// BlockReferenceManager.cpp 2 3#include <new> 4 5#include "AllocationInfo.h" 6#include "Block.h" 7#include "BlockAllocator.h" // only for BA_PANIC 8#include "BlockReferenceManager.h" 9#include "Debug.h" 10 11static const int kBlockReferenceTableSize = 128; 12 13// constructor 14BlockReferenceManager::BlockReferenceManager() 15 : fTables(10), 16 fFreeList(NULL) 17{ 18} 19 20// destructor 21BlockReferenceManager::~BlockReferenceManager() 22{ 23} 24 25// AllocateReference 26BlockReference * 27BlockReferenceManager::AllocateReference() 28{ 29 BlockReference *reference = NULL; 30 if (!fFreeList) 31 _AddTable(); 32 if (fFreeList) { 33 reference = fFreeList; 34 fFreeList = *(BlockReference**)fFreeList; 35 } 36 return reference; 37} 38 39// FreeReference 40void 41BlockReferenceManager::FreeReference(BlockReference *reference) 42{ 43 if (reference) { 44 *(BlockReference**)reference = fFreeList; 45 fFreeList = reference; 46 } 47} 48 49// CheckReference 50bool 51BlockReferenceManager::CheckReference(BlockReference *reference) 52{ 53 if (reference) { 54 uint32 address = (uint32)reference; 55 int32 tableCount = fTables.CountItems(); 56 for (int32 i = 0; i < tableCount; i++) { 57 Table *table = &fTables.ItemAt(i); 58 uint32 first = (uint32)table->GetReferences(); 59 uint32 last = (uint32)(table->GetReferences() + table->GetSize()); 60 if (first <= address && address < last) 61 return true; 62 } 63 } 64 FATAL(("BlockReference %p does not exist!\n", reference)); 65 BA_PANIC("BlockReference doesn't exist."); 66 return false; 67} 68 69// GetAllocationInfo 70void 71BlockReferenceManager::GetAllocationInfo(AllocationInfo &info) 72{ 73 info.AddListAllocation(fTables.GetCapacity(), sizeof(Table)); 74 int32 count = fTables.CountItems(); 75 for (int32 i = 0; i < count; i++) { 76 Table &table = fTables.ItemAt(i); 77 info.AddOtherAllocation(table.GetSize() * sizeof(BlockReference)); 78 } 79} 80 81// _AddTable 82status_t 83BlockReferenceManager::_AddTable() 84{ 85 status_t error = B_OK; 86 // add a new table 87 Table dummy; 88 if (fTables.AddItem(dummy)) { 89 int32 index = fTables.CountItems() - 1; 90 Table &table = fTables.ItemAt(index); 91 error = table.Init(kBlockReferenceTableSize); 92 if (error == B_OK) { 93 // add the references to the free list 94 uint32 count = table.GetSize(); 95 BlockReference *references = table.GetReferences(); 96 for (uint32 i = 0; i < count; i++) { 97 BlockReference *reference = references + i; 98 *(BlockReference**)reference = fFreeList; 99 fFreeList = reference; 100 } 101 } else 102 fTables.RemoveItem(index); 103 } else 104 SET_ERROR(error, B_NO_MEMORY); 105 return error; 106} 107 108 109// Table 110 111// destructor 112BlockReferenceManager::Table::~Table() 113{ 114 if (fReferences) 115 delete[] fReferences; 116} 117 118// Init 119status_t 120BlockReferenceManager::Table::Init(int32 size) 121{ 122 status_t error = (size > 0 ? B_OK : B_BAD_VALUE); 123 if (error == B_OK) { 124 fReferences = new(std::nothrow) BlockReference[size]; 125 if (fReferences) 126 fSize = size; 127 else 128 SET_ERROR(error, B_NO_MEMORY); 129 } 130 return error; 131} 132 133