Skip to content

Commit

Permalink
Try using C++17's aligned new, maybe works natively on MSYS?
Browse files Browse the repository at this point in the history
  • Loading branch information
LebedevRI committed Nov 12, 2023
1 parent a92735d commit ca9cf9e
Showing 1 changed file with 16 additions and 51 deletions.
67 changes: 16 additions & 51 deletions src/librawspeed/adt/AlignedAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#pragma once

#include "AddressSanitizer.h"
#include "adt/Invariant.h"
#include "common/Common.h"
#include "common/RawspeedException.h"
Expand All @@ -33,47 +32,6 @@

namespace rawspeed {

namespace impl {

[[nodiscard]] inline void* __attribute__((malloc, warn_unused_result,
alloc_size(1), alloc_align(2)))
alignedMalloc(size_t size, size_t alignment) {
invariant(isPowerOfTwo(alignment)); // for posix_memalign, _aligned_malloc
invariant(isAligned(alignment, sizeof(void*))); // for posix_memalign
invariant(isAligned(size, alignment)); // for aligned_alloc

void* ptr = nullptr;

#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
// workaround ASAN's broken allocator_may_return_null option
// plus, avoidance of libFuzzer's rss_limit_mb option
// if trying to alloc more than 2GB, just return null.
// else it would abort() the whole program...
if (size > 2UL << 30UL)
return ptr;
#endif

#if defined(_WIN32) || defined(_WIN64)
ptr = _aligned_malloc(size, alignment);
#else
ptr = std::aligned_alloc(alignment, size);
#endif

invariant(isAligned(ptr, alignment));

return ptr;
}

inline void alignedFree(void* ptr) {
#if defined(_WIN32) || defined(_WIN64)
_aligned_free(ptr);
#else
std::free(ptr); // NOLINT
#endif
}

} // namespace impl

template <class T, int alignment> class AlignedAllocator {
using self = AlignedAllocator<T, alignment>;
using allocator_traits = std::allocator_traits<self>;
Expand All @@ -86,30 +44,37 @@ template <class T, int alignment> class AlignedAllocator {
};

[[nodiscard]] T* allocate(std::size_t numElts) const {
static_assert(alignment >= alignof(T), "insufficient alignment");
static_assert(size_t(alignment) >= alignof(T), "insufficient alignment");
invariant(numElts > 0 && "Should not be trying to allocate no elements");
assert(numElts <= allocator_traits::max_size(*this) &&
"Can allocate this many elements.");
invariant(numElts <= SIZE_MAX / sizeof(T) &&
"Byte count calculation will not overflow");

std::size_t numBytes = sizeof(T) * numElts;
std::size_t numPaddedBytes = roundUp(numBytes, alignment);
invariant(numPaddedBytes >= numBytes &&
"Alignment did not cause wraparound.");

auto* r = static_cast<T*>(impl::alignedMalloc(numPaddedBytes, alignment));
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
// workaround ASAN's broken allocator_may_return_null option
// plus, avoidance of libFuzzer's rss_limit_mb option
// if trying to alloc more than 2GB, just return null.
// else it would abort() the whole program...
if (numBytes > 2UL << 30UL)
ThrowRSE("FUZZ alloc bailout (%zu bytes)", numBytes);
#endif

auto* r = static_cast<T*>(operator new(
numBytes, static_cast<std::align_val_t>(alignment)));
invariant(isAligned(r, alignment));

Check warning on line 67 in src/librawspeed/adt/AlignedAllocator.h

View check run for this annotation

Codecov / codecov/patch

src/librawspeed/adt/AlignedAllocator.h#L67

Added line #L67 was not covered by tests
if (!r)
ThrowRSE("Out of memory while trying to allocate %zu bytes",
numPaddedBytes);
ASan::PoisonMemoryRegion(r + numElts, numPaddedBytes - numBytes);
ThrowRSE("Out of memory while trying to allocate %zu bytes", numBytes);

Check warning on line 69 in src/librawspeed/adt/AlignedAllocator.h

View check run for this annotation

Codecov / codecov/patch

src/librawspeed/adt/AlignedAllocator.h#L69

Added line #L69 was not covered by tests
return r;
}

void deallocate(T* p, std::size_t n) const noexcept {
invariant(p);
invariant(n > 0);
impl::alignedFree(p);
invariant(isAligned(p, alignment));

Check warning on line 76 in src/librawspeed/adt/AlignedAllocator.h

View check run for this annotation

Codecov / codecov/patch

src/librawspeed/adt/AlignedAllocator.h#L76

Added line #L76 was not covered by tests
operator delete(p, static_cast<std::align_val_t>(alignment));
}

using propagate_on_container_copy_assignment = std::true_type;
Expand Down

0 comments on commit ca9cf9e

Please sign in to comment.