Program Listing for File AllocationMap.cpp¶
↰ Return to documentation for file (umpire/util/AllocationMap.cpp
)
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018, Lawrence Livermore National Security, LLC.
// Produced at the Lawrence Livermore National Laboratory
//
// Created by David Beckingsale, david@llnl.gov
// LLNL-CODE-747640
//
// All rights reserved.
//
// This file is part of Umpire.
//
// For details, see https://github.com/LLNL/Umpire
// Please also see the LICENSE file for MIT license.
//////////////////////////////////////////////////////////////////////////////
#include "umpire/util/AllocationMap.hpp"
#include "umpire/util/Macros.hpp"
#include "umpire/tpl/judy/judyL2Array.h"
namespace {
using AddressPair = judyL2Array<uintptr_t, uintptr_t>::cpair;
using EntryVector = judyL2Array<uintptr_t, uintptr_t>::vector;
using Entry = umpire::util::AllocationRecord*;
}
namespace umpire {
namespace util {
AllocationMap::AllocationMap() :
m_records(new judyL2Array<uintptr_t, uintptr_t>()),
m_mutex(new std::mutex())
{
}
AllocationMap::~AllocationMap()
{
}
void
AllocationMap::insert(void* ptr, AllocationRecord* alloc_record)
{
try {
UMPIRE_LOCK;
UMPIRE_LOG(Debug, "Inserting " << ptr);
m_records->insert(
reinterpret_cast<uintptr_t>(ptr),
reinterpret_cast<uintptr_t>(alloc_record));
UMPIRE_UNLOCK;
} catch (...) {
UMPIRE_UNLOCK;
throw;
}
}
AllocationRecord*
AllocationMap::remove(void* ptr)
{
Entry ret = nullptr;
try {
UMPIRE_LOCK;
UMPIRE_LOG(Debug, "Removing " << ptr);
EntryVector* record_vector =
const_cast<EntryVector*>(
m_records->find(reinterpret_cast<uintptr_t>(ptr)));
if (record_vector) {
if (record_vector->size() > 0) {
ret = reinterpret_cast<Entry>(record_vector->back());
record_vector->pop_back();
if (record_vector->empty()) {
m_records->removeEntry(reinterpret_cast<uintptr_t>(ptr));
}
}
} else {
UMPIRE_ERROR("Cannot remove " << ptr );
}
UMPIRE_UNLOCK;
} catch (...) {
UMPIRE_UNLOCK;
throw;
}
return ret;
}
AllocationRecord*
AllocationMap::findRecord(void* ptr)
{
Entry alloc_record = nullptr;
try {
UMPIRE_LOCK;
auto record = m_records->atOrBefore(reinterpret_cast<uintptr_t>(ptr));
if (record.value) {
void* parent_ptr = reinterpret_cast<void*>(record.key);
alloc_record =
reinterpret_cast<Entry>(record.value->back());
if (alloc_record &&
((static_cast<char*>(parent_ptr) + alloc_record->m_size)
> static_cast<char*>(ptr))) {
UMPIRE_LOG(Debug, "Found " << ptr << " at " << parent_ptr
<< " with size " << alloc_record->m_size);
}
}
UMPIRE_UNLOCK;
}
catch (...){
UMPIRE_UNLOCK;
throw;
}
return alloc_record;
}
AllocationRecord*
AllocationMap::find(void* ptr)
{
UMPIRE_LOG(Debug, "Searching for " << ptr);
auto alloc_record = findRecord(ptr);
if (alloc_record) {
return alloc_record;
} else {
#if !defined(NDEBUG)
// use this from a debugger to dump the contents of the AllocationMap
printAll();
#endif
UMPIRE_ERROR("Allocation not mapped: " << ptr);
}
}
bool
AllocationMap::contains(void* ptr)
{
UMPIRE_LOG(Debug, "Searching for " << ptr);
return (findRecord(ptr) != nullptr);
}
void
AllocationMap::printAll()
{
std::cout << "🔍 Printing allocation map contents..." << std::endl;
for (auto record = m_records->begin(); m_records->success(); record=m_records->next()){
auto addr = record.key;
auto vec = *record.value;
std::cout << reinterpret_cast<void*>(addr) << " : {" << std::endl;
for (auto const& records : vec) {
AllocationRecord* tmp = reinterpret_cast<AllocationRecord*>(records);
std::cout << " " << tmp->m_size <<
" [ " << reinterpret_cast<void*>(addr) <<
" -- " << reinterpret_cast<void*>(addr+tmp->m_size) <<
" ] " << std::endl;
}
std::cout << "}" << std::endl;
}
std::cout << "done." << std::endl;
}
} // end of namespace util
} // end of namespace umpire