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