Program Listing for File AlignedAllocator.cpp

Return to documentation for file (umpire/strategy/AlignedAllocator.cpp)

//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-20, Lawrence Livermore National Security, LLC and Umpire
// project contributors. See the COPYRIGHT file for details.
//
// SPDX-License-Identifier: (MIT)
//////////////////////////////////////////////////////////////////////////////
#include "umpire/strategy/AlignedAllocator.hpp"

#include "umpire/util/Macros.hpp"

namespace umpire {
namespace strategy {

AlignedAllocator::AlignedAllocator(
    const std::string& name,
    int id,
    Allocator allocator,
    std::size_t alignment) :
  AllocationStrategy(name, id),
  m_allocator(allocator.getAllocationStrategy()),
  m_alignment{alignment},
  m_mask{static_cast<uintptr_t>(~(m_alignment-1))}
{
  if (m_allocator->getPlatform() != Platform::host) {
    UMPIRE_ERROR("Cannot construct AlignedAllocator from non-host Allocator.");
  }

  if (! (m_alignment >= 16 && ((m_alignment & (m_alignment-1)) == 0))) {
    UMPIRE_ERROR("AlignedAllocator alignment must be a power of 2 greater than or equal to 16");
  }
}

void*
AlignedAllocator::allocate(std::size_t bytes)
{
  std::size_t total_bytes = bytes+sizeof(void*)+m_alignment-1;
  UMPIRE_LOG(Debug, "requested: " << bytes << " actual: " << bytes+m_alignment-1);

  uintptr_t ptr{reinterpret_cast<uintptr_t>(m_allocator->allocate(total_bytes))};
  uintptr_t aligned_ptr{static_cast<uintptr_t>((ptr + sizeof(void*) + (m_alignment-1)) & m_mask)};
  uintptr_t* header = (uintptr_t*) (aligned_ptr - sizeof(void*));
  *header = ptr;

  UMPIRE_LOG(Debug, "ptr: " << reinterpret_cast<void*>(ptr) << " aligned: " << reinterpret_cast<void*>(aligned_ptr));
  return reinterpret_cast<void*>(aligned_ptr);
}

void
AlignedAllocator::deallocate(void* ptr)
{
  uintptr_t aligned_ptr{reinterpret_cast<uintptr_t>(ptr)};
  uintptr_t* header = (uintptr_t*) (aligned_ptr - sizeof(void*));
  void* base_ptr = reinterpret_cast<void*>(*header);

  UMPIRE_LOG(Debug, "ptr: " << reinterpret_cast<void*>(ptr) << " base_ptr: " << reinterpret_cast<void*>(base_ptr));
  return m_allocator->deallocate(base_ptr);
}

Platform
AlignedAllocator::getPlatform() noexcept
{
  return m_allocator->getPlatform();
}

MemoryResourceTraits
AlignedAllocator::getTraits() const noexcept
{
  return m_allocator->getTraits();
}

} // end of namespace strategy
} // end of namespace umpire