194e3ee44SDavid Chisnall /*
294e3ee44SDavid Chisnall * Copyright 2010-2011 PathScale, Inc. All rights reserved.
394e3ee44SDavid Chisnall *
494e3ee44SDavid Chisnall * Redistribution and use in source and binary forms, with or without
594e3ee44SDavid Chisnall * modification, are permitted provided that the following conditions are met:
694e3ee44SDavid Chisnall *
794e3ee44SDavid Chisnall * 1. Redistributions of source code must retain the above copyright notice,
894e3ee44SDavid Chisnall * this list of conditions and the following disclaimer.
994e3ee44SDavid Chisnall *
1094e3ee44SDavid Chisnall * 2. Redistributions in binary form must reproduce the above copyright notice,
1194e3ee44SDavid Chisnall * this list of conditions and the following disclaimer in the documentation
1294e3ee44SDavid Chisnall * and/or other materials provided with the distribution.
1394e3ee44SDavid Chisnall *
1494e3ee44SDavid Chisnall * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
1594e3ee44SDavid Chisnall * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1694e3ee44SDavid Chisnall * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1794e3ee44SDavid Chisnall * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
1894e3ee44SDavid Chisnall * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1994e3ee44SDavid Chisnall * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2094e3ee44SDavid Chisnall * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2194e3ee44SDavid Chisnall * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2294e3ee44SDavid Chisnall * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2394e3ee44SDavid Chisnall * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2494e3ee44SDavid Chisnall * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2594e3ee44SDavid Chisnall */
2694e3ee44SDavid Chisnall
277a984708SDavid Chisnall /**
287a984708SDavid Chisnall * memory.cc - Contains stub definition of C++ new/delete operators.
297a984708SDavid Chisnall *
307a984708SDavid Chisnall * These definitions are intended to be used for testing and are weak symbols
317a984708SDavid Chisnall * to allow them to be replaced by definitions from a STL implementation.
327a984708SDavid Chisnall * These versions simply wrap malloc() and free(), they do not provide a
337a984708SDavid Chisnall * C++-specific allocator.
347a984708SDavid Chisnall */
357a984708SDavid Chisnall
367a984708SDavid Chisnall #include <stddef.h>
377a984708SDavid Chisnall #include <stdlib.h>
387a984708SDavid Chisnall #include "stdexcept.h"
39f7cb1657SDavid Chisnall #include "atomic.h"
407a984708SDavid Chisnall
41db47c4bfSDavid Chisnall
427a984708SDavid Chisnall namespace std
437a984708SDavid Chisnall {
447a984708SDavid Chisnall struct nothrow_t {};
457a984708SDavid Chisnall }
467a984708SDavid Chisnall
477a984708SDavid Chisnall
487a984708SDavid Chisnall /// The type of the function called when allocation fails.
497a984708SDavid Chisnall typedef void (*new_handler)();
507a984708SDavid Chisnall /**
517a984708SDavid Chisnall * The function to call when allocation fails. By default, there is no
527a984708SDavid Chisnall * handler and a bad allocation exception is thrown if an allocation fails.
537a984708SDavid Chisnall */
54bfffb66eSDimitry Andric static atomic<new_handler> new_handl{nullptr};
557a984708SDavid Chisnall
567a984708SDavid Chisnall namespace std
577a984708SDavid Chisnall {
587a984708SDavid Chisnall /**
597a984708SDavid Chisnall * Sets a function to be called when there is a failure in new.
607a984708SDavid Chisnall */
617a984708SDavid Chisnall __attribute__((weak))
set_new_handler(new_handler handler)627a984708SDavid Chisnall new_handler set_new_handler(new_handler handler)
637a984708SDavid Chisnall {
64bfffb66eSDimitry Andric return new_handl.exchange(handler);
65f7cb1657SDavid Chisnall }
66bfffb66eSDimitry Andric
67f7cb1657SDavid Chisnall __attribute__((weak))
get_new_handler(void)68f7cb1657SDavid Chisnall new_handler get_new_handler(void)
69f7cb1657SDavid Chisnall {
70bfffb66eSDimitry Andric return new_handl.load();
717a984708SDavid Chisnall }
727a984708SDavid Chisnall }
737a984708SDavid Chisnall
747a984708SDavid Chisnall
75076e75ebSDimitry Andric #if __cplusplus < 201103L
76076e75ebSDimitry Andric #define BADALLOC throw(std::bad_alloc)
77076e75ebSDimitry Andric #else
78076e75ebSDimitry Andric #define BADALLOC
79076e75ebSDimitry Andric #endif
80076e75ebSDimitry Andric
8156aaed38SDimitry Andric namespace
8256aaed38SDimitry Andric {
8356aaed38SDimitry Andric /**
8456aaed38SDimitry Andric * Helper for forwarding from no-throw operators to versions that can
8556aaed38SDimitry Andric * return nullptr. Catches any exception and converts it into a nullptr
8656aaed38SDimitry Andric * return.
8756aaed38SDimitry Andric */
8856aaed38SDimitry Andric template<void*(New)(size_t)>
noexcept_new(size_t size)8956aaed38SDimitry Andric void *noexcept_new(size_t size)
9056aaed38SDimitry Andric {
9156aaed38SDimitry Andric #if !defined(_CXXRT_NO_EXCEPTIONS)
9256aaed38SDimitry Andric try
9356aaed38SDimitry Andric {
9456aaed38SDimitry Andric return New(size);
9556aaed38SDimitry Andric } catch (...)
9656aaed38SDimitry Andric {
9756aaed38SDimitry Andric // nothrow operator new should return NULL in case of
9856aaed38SDimitry Andric // std::bad_alloc exception in new handler
9956aaed38SDimitry Andric return nullptr;
10056aaed38SDimitry Andric }
10156aaed38SDimitry Andric #else
10256aaed38SDimitry Andric return New(size);
10356aaed38SDimitry Andric #endif
10456aaed38SDimitry Andric }
10556aaed38SDimitry Andric }
10656aaed38SDimitry Andric
107076e75ebSDimitry Andric
1087a984708SDavid Chisnall __attribute__((weak))
operator new(size_t size)109076e75ebSDimitry Andric void* operator new(size_t size) BADALLOC
1107a984708SDavid Chisnall {
111f7cb1657SDavid Chisnall if (0 == size)
112f7cb1657SDavid Chisnall {
113f7cb1657SDavid Chisnall size = 1;
114f7cb1657SDavid Chisnall }
1157a984708SDavid Chisnall void * mem = malloc(size);
1167a984708SDavid Chisnall while (0 == mem)
1177a984708SDavid Chisnall {
118f7cb1657SDavid Chisnall new_handler h = std::get_new_handler();
119f7cb1657SDavid Chisnall if (0 != h)
1207a984708SDavid Chisnall {
121f7cb1657SDavid Chisnall h();
1227a984708SDavid Chisnall }
1237a984708SDavid Chisnall else
1247a984708SDavid Chisnall {
12556aaed38SDimitry Andric #if !defined(_CXXRT_NO_EXCEPTIONS)
1267a984708SDavid Chisnall throw std::bad_alloc();
12756aaed38SDimitry Andric #else
12856aaed38SDimitry Andric break;
12956aaed38SDimitry Andric #endif
1307a984708SDavid Chisnall }
1317a984708SDavid Chisnall mem = malloc(size);
1327a984708SDavid Chisnall }
1337a984708SDavid Chisnall
1347a984708SDavid Chisnall return mem;
1357a984708SDavid Chisnall }
1367a984708SDavid Chisnall
13756aaed38SDimitry Andric
1387a984708SDavid Chisnall __attribute__((weak))
operator new(size_t size,const std::nothrow_t &)139*13da1af1SEd Maste void* operator new(size_t size, const std::nothrow_t &) _LIBCXXRT_NOEXCEPT
1407a984708SDavid Chisnall {
14156aaed38SDimitry Andric return noexcept_new<(::operator new)>(size);
1427a984708SDavid Chisnall }
1437a984708SDavid Chisnall
1447a984708SDavid Chisnall
1457a984708SDavid Chisnall __attribute__((weak))
operator delete(void * ptr)146*13da1af1SEd Maste void operator delete(void * ptr) _LIBCXXRT_NOEXCEPT
1477a984708SDavid Chisnall {
1487a984708SDavid Chisnall free(ptr);
1497a984708SDavid Chisnall }
1507a984708SDavid Chisnall
1517a984708SDavid Chisnall
1527a984708SDavid Chisnall __attribute__((weak))
operator new[](size_t size)153076e75ebSDimitry Andric void * operator new[](size_t size) BADALLOC
1547a984708SDavid Chisnall {
1557a984708SDavid Chisnall return ::operator new(size);
1567a984708SDavid Chisnall }
1577a984708SDavid Chisnall
1587a984708SDavid Chisnall
1597a984708SDavid Chisnall __attribute__((weak))
operator new[](size_t size,const std::nothrow_t &)160*13da1af1SEd Maste void * operator new[](size_t size, const std::nothrow_t &) _LIBCXXRT_NOEXCEPT
1614bab9fd9SDavid Chisnall {
16256aaed38SDimitry Andric return noexcept_new<(::operator new[])>(size);
1634bab9fd9SDavid Chisnall }
1644bab9fd9SDavid Chisnall
1654bab9fd9SDavid Chisnall
1664bab9fd9SDavid Chisnall __attribute__((weak))
operator delete[](void * ptr)167*13da1af1SEd Maste void operator delete[](void * ptr) _LIBCXXRT_NOEXCEPT
1687a984708SDavid Chisnall {
1697a984708SDavid Chisnall ::operator delete(ptr);
1707a984708SDavid Chisnall }
1717a984708SDavid Chisnall
172e91d723aSDimitry Andric // C++14 additional delete operators
1737a984708SDavid Chisnall
174e91d723aSDimitry Andric #if __cplusplus >= 201402L
175e91d723aSDimitry Andric
176e91d723aSDimitry Andric __attribute__((weak))
operator delete(void * ptr,size_t)177*13da1af1SEd Maste void operator delete(void * ptr, size_t) _LIBCXXRT_NOEXCEPT
178e91d723aSDimitry Andric {
179e91d723aSDimitry Andric ::operator delete(ptr);
180e91d723aSDimitry Andric }
181e91d723aSDimitry Andric
182e91d723aSDimitry Andric
183e91d723aSDimitry Andric __attribute__((weak))
operator delete[](void * ptr,size_t)184*13da1af1SEd Maste void operator delete[](void * ptr, size_t) _LIBCXXRT_NOEXCEPT
185e91d723aSDimitry Andric {
186e91d723aSDimitry Andric ::operator delete(ptr);
187e91d723aSDimitry Andric }
188e91d723aSDimitry Andric
189e91d723aSDimitry Andric #endif
190