xref: /freebsd/contrib/libcxxrt/memory.cc (revision 4bab9fd9640e28bf1d8ba8344d443909b7937aa2)
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  */
547a984708SDavid Chisnall static new_handler new_handl;
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))
627a984708SDavid Chisnall 	new_handler set_new_handler(new_handler handler)
637a984708SDavid Chisnall 	{
64f7cb1657SDavid Chisnall 		return ATOMIC_SWAP(&new_handl, handler);
65f7cb1657SDavid Chisnall 	}
66f7cb1657SDavid Chisnall 	__attribute__((weak))
67f7cb1657SDavid Chisnall 	new_handler get_new_handler(void)
68f7cb1657SDavid Chisnall 	{
69f7cb1657SDavid Chisnall 		return ATOMIC_LOAD(&new_handl);
707a984708SDavid Chisnall 	}
717a984708SDavid Chisnall }
727a984708SDavid Chisnall 
737a984708SDavid Chisnall 
747a984708SDavid Chisnall __attribute__((weak))
757a984708SDavid Chisnall void* operator new(size_t size)
767a984708SDavid Chisnall {
77f7cb1657SDavid Chisnall 	if (0 == size)
78f7cb1657SDavid Chisnall 	{
79f7cb1657SDavid Chisnall 		size = 1;
80f7cb1657SDavid Chisnall 	}
817a984708SDavid Chisnall 	void * mem = malloc(size);
827a984708SDavid Chisnall 	while (0 == mem)
837a984708SDavid Chisnall 	{
84f7cb1657SDavid Chisnall 		new_handler h = std::get_new_handler();
85f7cb1657SDavid Chisnall 		if (0 != h)
867a984708SDavid Chisnall 		{
87f7cb1657SDavid Chisnall 			h();
887a984708SDavid Chisnall 		}
897a984708SDavid Chisnall 		else
907a984708SDavid Chisnall 		{
917a984708SDavid Chisnall 			throw std::bad_alloc();
927a984708SDavid Chisnall 		}
937a984708SDavid Chisnall 		mem = malloc(size);
947a984708SDavid Chisnall 	}
957a984708SDavid Chisnall 
967a984708SDavid Chisnall 	return mem;
977a984708SDavid Chisnall }
987a984708SDavid Chisnall 
997a984708SDavid Chisnall __attribute__((weak))
1007a984708SDavid Chisnall void* operator new(size_t size, const std::nothrow_t &) throw()
1017a984708SDavid Chisnall {
102*4bab9fd9SDavid Chisnall 	try {
103*4bab9fd9SDavid Chisnall 		return :: operator new(size);
104*4bab9fd9SDavid Chisnall 	} catch (...) {
1057a984708SDavid Chisnall 		// nothrow operator new should return NULL in case of
1067a984708SDavid Chisnall 		// std::bad_alloc exception in new handler
1077a984708SDavid Chisnall 		return NULL;
1087a984708SDavid Chisnall 	}
1097a984708SDavid Chisnall }
1107a984708SDavid Chisnall 
1117a984708SDavid Chisnall 
1127a984708SDavid Chisnall __attribute__((weak))
1137a984708SDavid Chisnall void operator delete(void * ptr)
114*4bab9fd9SDavid Chisnall #if __cplusplus < 201000L
115*4bab9fd9SDavid Chisnall throw()
116*4bab9fd9SDavid Chisnall #endif
1177a984708SDavid Chisnall {
1187a984708SDavid Chisnall 	free(ptr);
1197a984708SDavid Chisnall }
1207a984708SDavid Chisnall 
1217a984708SDavid Chisnall 
1227a984708SDavid Chisnall __attribute__((weak))
1237a984708SDavid Chisnall void * operator new[](size_t size)
124*4bab9fd9SDavid Chisnall #if __cplusplus < 201000L
125*4bab9fd9SDavid Chisnall throw(std::bad_alloc)
126*4bab9fd9SDavid Chisnall #endif
1277a984708SDavid Chisnall {
1287a984708SDavid Chisnall 	return ::operator new(size);
1297a984708SDavid Chisnall }
1307a984708SDavid Chisnall 
1317a984708SDavid Chisnall 
1327a984708SDavid Chisnall __attribute__((weak))
133*4bab9fd9SDavid Chisnall void * operator new[](size_t size, const std::nothrow_t &) throw()
134*4bab9fd9SDavid Chisnall {
135*4bab9fd9SDavid Chisnall 	try {
136*4bab9fd9SDavid Chisnall 		return ::operator new[](size);
137*4bab9fd9SDavid Chisnall 	} catch (...) {
138*4bab9fd9SDavid Chisnall 		// nothrow operator new should return NULL in case of
139*4bab9fd9SDavid Chisnall 		// std::bad_alloc exception in new handler
140*4bab9fd9SDavid Chisnall 		return NULL;
141*4bab9fd9SDavid Chisnall 	}
142*4bab9fd9SDavid Chisnall }
143*4bab9fd9SDavid Chisnall 
144*4bab9fd9SDavid Chisnall 
145*4bab9fd9SDavid Chisnall __attribute__((weak))
146*4bab9fd9SDavid Chisnall void operator delete[](void * ptr)
147*4bab9fd9SDavid Chisnall #if __cplusplus < 201000L
148*4bab9fd9SDavid Chisnall throw()
149*4bab9fd9SDavid Chisnall #endif
1507a984708SDavid Chisnall {
1517a984708SDavid Chisnall 	::operator delete(ptr);
1527a984708SDavid Chisnall }
1537a984708SDavid Chisnall 
1547a984708SDavid Chisnall 
155