memory.cc revision 253222
1276479Sdim/* 2249259Sdim * Copyright 2010-2011 PathScale, Inc. All rights reserved. 3249259Sdim * 4249259Sdim * Redistribution and use in source and binary forms, with or without 5249259Sdim * modification, are permitted provided that the following conditions are met: 6249259Sdim * 7249259Sdim * 1. Redistributions of source code must retain the above copyright notice, 8249259Sdim * this list of conditions and the following disclaimer. 9249259Sdim * 10276479Sdim * 2. Redistributions in binary form must reproduce the above copyright notice, 11249259Sdim * this list of conditions and the following disclaimer in the documentation 12249259Sdim * and/or other materials provided with the distribution. 13249259Sdim * 14249259Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 15280031Sdim * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16280031Sdim * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17276479Sdim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 18276479Sdim * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19249259Sdim * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20249259Sdim * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21276479Sdim * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22276479Sdim * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23249259Sdim * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24249259Sdim * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25249259Sdim */ 26249259Sdim 27276479Sdim/** 28288943Sdim * memory.cc - Contains stub definition of C++ new/delete operators. 29276479Sdim * 30276479Sdim * These definitions are intended to be used for testing and are weak symbols 31276479Sdim * to allow them to be replaced by definitions from a STL implementation. 32276479Sdim * These versions simply wrap malloc() and free(), they do not provide a 33276479Sdim * C++-specific allocator. 34276479Sdim */ 35276479Sdim 36249259Sdim#include <stddef.h> 37249259Sdim#include <stdlib.h> 38276479Sdim#include "stdexcept.h" 39276479Sdim#include "atomic.h" 40276479Sdim 41276479Sdim 42276479Sdimnamespace std 43276479Sdim{ 44276479Sdim struct nothrow_t {}; 45276479Sdim} 46276479Sdim 47276479Sdim 48276479Sdim/// The type of the function called when allocation fails. 49276479Sdimtypedef void (*new_handler)(); 50276479Sdim/** 51280865Semaste * The function to call when allocation fails. By default, there is no 52280865Semaste * handler and a bad allocation exception is thrown if an allocation fails. 53276479Sdim */ 54280865Semastestatic new_handler new_handl; 55280865Semaste 56280865Semastenamespace std 57280865Semaste{ 58280865Semaste /** 59280865Semaste * Sets a function to be called when there is a failure in new. 60280865Semaste */ 61276479Sdim __attribute__((weak)) 62296417Sdim new_handler set_new_handler(new_handler handler) 63296417Sdim { 64296417Sdim return ATOMIC_SWAP(&new_handl, handler); 65288943Sdim } 66288943Sdim __attribute__((weak)) 67288943Sdim new_handler get_new_handler(void) 68280865Semaste { 69276479Sdim return ATOMIC_LOAD(&new_handl); 70276479Sdim } 71276479Sdim} 72276479Sdim 73276479Sdim 74249259Sdim__attribute__((weak)) 75249259Sdimvoid* operator new(size_t size) 76276479Sdim{ 77276479Sdim if (0 == size) 78276479Sdim { 79249259Sdim size = 1; 80261991Sdim } 81261991Sdim void * mem = malloc(size); 82261991Sdim while (0 == mem) 83261991Sdim { 84261991Sdim new_handler h = std::get_new_handler(); 85261991Sdim if (0 != h) 86261991Sdim { 87261991Sdim h(); 88276479Sdim } 89276479Sdim else 90276479Sdim { 91276479Sdim throw std::bad_alloc(); 92276479Sdim } 93276479Sdim mem = malloc(size); 94276479Sdim } 95276479Sdim 96276479Sdim return mem; 97280031Sdim} 98276479Sdim 99276479Sdim__attribute__((weak)) 100276479Sdimvoid* operator new(size_t size, const std::nothrow_t &) throw() 101276479Sdim{ 102276479Sdim try { 103276479Sdim return :: operator new(size); 104276479Sdim } catch (...) { 105280031Sdim // nothrow operator new should return NULL in case of 106261991Sdim // std::bad_alloc exception in new handler 107261991Sdim return NULL; 108276479Sdim } 109288943Sdim} 110249259Sdim 111276479Sdim 112249259Sdim__attribute__((weak)) 113249259Sdimvoid operator delete(void * ptr) 114276479Sdim#if __cplusplus < 201000L 115276479Sdimthrow() 116276479Sdim#endif 117276479Sdim{ 118276479Sdim free(ptr); 119249259Sdim} 120249259Sdim 121249259Sdim 122249259Sdim__attribute__((weak)) 123249259Sdimvoid * operator new[](size_t size) 124249259Sdim#if __cplusplus < 201000L 125249259Sdimthrow(std::bad_alloc) 126249259Sdim#endif 127249259Sdim{ 128249259Sdim return ::operator new(size); 129249259Sdim} 130249259Sdim 131249259Sdim 132249259Sdim__attribute__((weak)) 133249259Sdimvoid * operator new[](size_t size, const std::nothrow_t &) throw() 134276479Sdim{ 135276479Sdim try { 136276479Sdim return ::operator new[](size); 137249259Sdim } catch (...) { 138249259Sdim // nothrow operator new should return NULL in case of 139249259Sdim // std::bad_alloc exception in new handler 140276479Sdim return NULL; 141249259Sdim } 142276479Sdim} 143276479Sdim 144276479Sdim 145276479Sdim__attribute__((weak)) 146249259Sdimvoid operator delete[](void * ptr) 147249259Sdim#if __cplusplus < 201000L 148249259Sdimthrow() 149276479Sdim#endif 150276479Sdim{ 151276479Sdim ::operator delete(ptr); 152276479Sdim} 153276479Sdim 154276479Sdim 155276479Sdim