/*
* Copyright 2011, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "TeamMemoryBlockManager.h"
#include <new>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "TeamMemoryBlock.h"
struct TeamMemoryBlockManager::Key {
target_addr_t address;
Key(target_addr_t address)
:
address(address)
{
}
uint32 HashValue() const
{
return (uint32)address;
}
bool operator==(const Key& other) const
{
return address == other.address;
}
};
struct TeamMemoryBlockManager::MemoryBlockEntry : Key {
TeamMemoryBlock* block;
MemoryBlockEntry* next;
MemoryBlockEntry(TeamMemoryBlock* block)
:
Key(block->BaseAddress()),
block(block)
{
}
~MemoryBlockEntry()
{
}
};
struct TeamMemoryBlockManager::MemoryBlockHashDefinition {
typedef Key KeyType;
typedef MemoryBlockEntry ValueType;
size_t HashKey(const Key& key) const
{
return key.HashValue();
}
size_t Hash(const MemoryBlockEntry* value) const
{
return value->HashValue();
}
bool Compare(const Key& key, const MemoryBlockEntry* value) const
{
return key == *value;
}
MemoryBlockEntry*& GetLink(MemoryBlockEntry* value) const
{
return value->next;
}
};
TeamMemoryBlockManager::TeamMemoryBlockManager()
:
fActiveBlocks(NULL),
fDeadBlocks(NULL)
{
}
TeamMemoryBlockManager::~TeamMemoryBlockManager()
{
_Cleanup();
}
status_t
TeamMemoryBlockManager::Init()
{
status_t result = fLock.InitCheck();
if (result != B_OK)
return result;
fActiveBlocks = new(std::nothrow) MemoryBlockTable();
if (fActiveBlocks == NULL)
return B_NO_MEMORY;
ObjectDeleter<MemoryBlockTable> activeDeleter(fActiveBlocks);
result = fActiveBlocks->Init();
if (result != B_OK)
return result;
fDeadBlocks = new(std::nothrow) DeadBlockTable();
if (fDeadBlocks == NULL)
return B_NO_MEMORY;
activeDeleter.Detach();
return B_OK;
}
TeamMemoryBlock*
TeamMemoryBlockManager::GetMemoryBlock(target_addr_t address)
{
AutoLocker<BLocker> lock(fLock);
address &= ~(B_PAGE_SIZE - 1);
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
if (entry != NULL) {
if (entry->block->AcquireReference() != 0)
return entry->block;
// this block already had its last reference released,
// move it to the dead list and create a new one instead.
_MarkDeadBlock(address);
}
TeamMemoryBlockOwner* owner = new(std::nothrow) TeamMemoryBlockOwner(this);
if (owner == NULL)
return NULL;
ObjectDeleter<TeamMemoryBlockOwner> ownerDeleter(owner);
TeamMemoryBlock* block = new(std::nothrow) TeamMemoryBlock(address,
owner);
if (block == NULL)
return NULL;
ObjectDeleter<TeamMemoryBlock> blockDeleter(block);
entry = new(std::nothrow) MemoryBlockEntry(block);
if (entry == NULL)
return NULL;
ownerDeleter.Detach();
blockDeleter.Detach();
fActiveBlocks->Insert(entry);
return entry->block;
}
void
TeamMemoryBlockManager::_Cleanup()
{
if (fActiveBlocks != NULL) {
MemoryBlockEntry* entry = fActiveBlocks->Clear(true);
while (entry != NULL) {
MemoryBlockEntry* next = entry->next;
delete entry;
entry = next;
}
delete fActiveBlocks;
fActiveBlocks = NULL;
}
}
void
TeamMemoryBlockManager::_MarkDeadBlock(target_addr_t address)
{
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
if (entry != NULL) {
fActiveBlocks->Remove(entry);
fDeadBlocks->Insert(entry->block);
delete entry;
}
}
void
TeamMemoryBlockManager::_RemoveBlock(target_addr_t address)
{
AutoLocker<BLocker> lock(fLock);
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
if (entry != NULL) {
fActiveBlocks->Remove(entry);
delete entry;
return;
}
DeadBlockTable::Iterator iterator = fDeadBlocks->GetIterator();
while (iterator.HasNext()) {
TeamMemoryBlock* block = iterator.Next();
if (block->BaseAddress() == address) {
fDeadBlocks->Remove(block);
break;
}
}
}
TeamMemoryBlockOwner::TeamMemoryBlockOwner(TeamMemoryBlockManager* manager)
:
fBlockManager(manager)
{
}
TeamMemoryBlockOwner::~TeamMemoryBlockOwner()
{
}
void
TeamMemoryBlockOwner::RemoveBlock(TeamMemoryBlock* block)
{
fBlockManager->_RemoveBlock(block->BaseAddress());
}
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: next.