blob: 20567a2fd8022516085eb0e66a9720f9dab9ce79 [file] [log] [blame]
// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT
#pragma once
/**
* This file contains concrete implementations of the C++ replaceable new and
* delete functions, as thin wrappers around calls to the allocator
* compartment.
*
* These are intended to be small and inlined for normal use but have blocking
* behaviour that may be inappropriate for some uses. Individual compartments
* can opt out of these definitions by defining `CHERIOT_NO_NEW_DELETE`.
*
* The `CHERIOT_NO_AMBIENT_MALLOC` macro will also hide these, because they
* depend on having ambient authority to allocate memory.
*/
#include_next <new>
#include <stdlib.h>
#if !defined(CHERIOT_NO_NEW_DELETE) && !defined(CHERIOT_NO_AMBIENT_MALLOC)
namespace std
{
/**
* Implementation details.
*/
namespace __new_detail
{
/**
* Class for managing the handler for new and delete.
*/
class NewHelper
{
/**
* Pointer to the handler for allocation failures.
*/
static inline std::new_handler newHandler;
/// The standard getter is allowed to access the new handler
friend std::new_handler std::get_new_handler() _NOEXCEPT;
/// The standard setter is allowed to modify the new handler
friend std::new_handler std::set_new_handler(new_handler) _NOEXCEPT;
public:
/**
* Helper to call the allocator and raise an error if allocation fails.
*/
static inline void *allocate(size_t size)
{
void *ptr = malloc(size);
while (ptr == nullptr)
{
if (newHandler)
{
newHandler();
}
else
{
break;
}
}
return ptr;
}
};
} // namespace __new_detail
/**
* Return the handler for allocation failure.
*/
inline new_handler get_new_handler() noexcept
{
return __new_detail::NewHelper::newHandler;
}
/**
* Set the handler for allocation failure and return the old one.
*
* Note: This implementation is *not* thread safe!
*/
inline new_handler set_new_handler(new_handler new_p) noexcept
{
auto old = __new_detail::NewHelper::newHandler;
__new_detail::NewHelper::newHandler = new_p;
return old;
}
} // namespace std
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Winline-new-delete"
_LIBCPP_NODISCARD_AFTER_CXX17
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void *
operator new(std::size_t size)
{
return std::__new_detail::NewHelper::allocate(size);
}
_LIBCPP_NODISCARD_AFTER_CXX17
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void *
operator new(std::size_t size, const std::nothrow_t &) noexcept
{
return std::__new_detail::NewHelper::allocate(size);
}
_LIBCPP_NODISCARD_AFTER_CXX17
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void *
operator new[](std::size_t size)
{
return std::__new_detail::NewHelper::allocate(size);
}
_LIBCPP_NODISCARD_AFTER_CXX17
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void *
operator new[](std::size_t size, const std::nothrow_t &) noexcept
{
return std::__new_detail::NewHelper::allocate(size);
}
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void
operator delete(void *ptr) noexcept
{
::free(ptr);
}
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void
operator delete(void *ptr, std::size_t size) noexcept
{
::free(ptr);
}
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void
operator delete[](void *ptr) noexcept
{
::free(ptr);
}
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void
operator delete[](void *ptr, std::size_t size) noexcept
{
::free(ptr);
}
__always_inline _LIBCPP_OVERRIDABLE_FUNC_VIS inline void
operator delete[](void *ptr, const std::nothrow_t &) noexcept
{
::free(ptr);
}
# if 0
// Until the allocator exposes a memalign interface, we don't support aligned allocation.
[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment);
[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment,
const std::nothrow_t&) noexcept;
void operator delete(void *ptr, std::align_val_t alignment) noexcept;
void operator delete(void *ptr,
std::size_t size,
std::align_val_t alignment) noexcept;
void operator delete(void *ptr, const std::nothrow_t &) noexcept;
void operator delete(void *ptr,
std::align_val_t alignment,
const std::nothrow_t &) noexcept;
[[nodiscard]] void *operator new[](std::size_t size,
std::align_val_t alignment);
[[nodiscard]] void *operator new[](std::size_t size,
std::align_val_t alignment,
const std::nothrow_t &) noexcept;
void operator delete[](void *ptr, std::align_val_t alignment) noexcept;
void operator delete[](void *ptr,
std::size_t size,
std::align_val_t alignment) noexcept;
void operator delete[](void *ptr,
std::align_val_t alignment,
const std::nothrow_t &) noexcept;
# endif
# pragma clang diagnostic pop
#endif