xref: /freebsd/contrib/libcxxrt/memory.cc (revision 94e3ee44c3581ff37c5e01b5ffe5eb16d30079a7)
1*94e3ee44SDavid Chisnall /*
2*94e3ee44SDavid Chisnall  * Copyright 2010-2011 PathScale, Inc. All rights reserved.
3*94e3ee44SDavid Chisnall  *
4*94e3ee44SDavid Chisnall  * Redistribution and use in source and binary forms, with or without
5*94e3ee44SDavid Chisnall  * modification, are permitted provided that the following conditions are met:
6*94e3ee44SDavid Chisnall  *
7*94e3ee44SDavid Chisnall  * 1. Redistributions of source code must retain the above copyright notice,
8*94e3ee44SDavid Chisnall  *    this list of conditions and the following disclaimer.
9*94e3ee44SDavid Chisnall  *
10*94e3ee44SDavid Chisnall  * 2. Redistributions in binary form must reproduce the above copyright notice,
11*94e3ee44SDavid Chisnall  *    this list of conditions and the following disclaimer in the documentation
12*94e3ee44SDavid Chisnall  *    and/or other materials provided with the distribution.
13*94e3ee44SDavid Chisnall  *
14*94e3ee44SDavid Chisnall  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
15*94e3ee44SDavid Chisnall  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*94e3ee44SDavid Chisnall  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*94e3ee44SDavid Chisnall  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18*94e3ee44SDavid Chisnall  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*94e3ee44SDavid Chisnall  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*94e3ee44SDavid Chisnall  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*94e3ee44SDavid Chisnall  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*94e3ee44SDavid Chisnall  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*94e3ee44SDavid Chisnall  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24*94e3ee44SDavid Chisnall  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*94e3ee44SDavid Chisnall  */
26*94e3ee44SDavid 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"
397a984708SDavid Chisnall 
40*94e3ee44SDavid Chisnall #ifndef __has_builtin
41*94e3ee44SDavid Chisnall #define __has_builtin(x) 0
42*94e3ee44SDavid Chisnall #endif
43*94e3ee44SDavid Chisnall 
44db47c4bfSDavid Chisnall #if !__has_builtin(__sync_swap)
45db47c4bfSDavid Chisnall #define __sync_swap __sync_lock_test_and_set
46db47c4bfSDavid Chisnall #endif
47db47c4bfSDavid Chisnall 
487a984708SDavid Chisnall namespace std
497a984708SDavid Chisnall {
507a984708SDavid Chisnall 	struct nothrow_t {};
517a984708SDavid Chisnall }
527a984708SDavid Chisnall 
537a984708SDavid Chisnall 
547a984708SDavid Chisnall /// The type of the function called when allocation fails.
557a984708SDavid Chisnall typedef void (*new_handler)();
567a984708SDavid Chisnall /**
577a984708SDavid Chisnall  * The function to call when allocation fails.  By default, there is no
587a984708SDavid Chisnall  * handler and a bad allocation exception is thrown if an allocation fails.
597a984708SDavid Chisnall  */
607a984708SDavid Chisnall static new_handler new_handl;
617a984708SDavid Chisnall 
627a984708SDavid Chisnall namespace std
637a984708SDavid Chisnall {
647a984708SDavid Chisnall 	/**
657a984708SDavid Chisnall 	 * Sets a function to be called when there is a failure in new.
667a984708SDavid Chisnall 	 */
677a984708SDavid Chisnall 	__attribute__((weak))
687a984708SDavid Chisnall 	new_handler set_new_handler(new_handler handler)
697a984708SDavid Chisnall 	{
70db47c4bfSDavid Chisnall 		return __sync_swap(&new_handl, handler);
717a984708SDavid Chisnall 	}
727a984708SDavid Chisnall }
737a984708SDavid Chisnall 
747a984708SDavid Chisnall 
757a984708SDavid Chisnall __attribute__((weak))
767a984708SDavid Chisnall void* operator new(size_t size)
777a984708SDavid Chisnall {
787a984708SDavid Chisnall 	void * mem = malloc(size);
797a984708SDavid Chisnall 	while (0 == mem)
807a984708SDavid Chisnall 	{
817a984708SDavid Chisnall 		if (0 != new_handl)
827a984708SDavid Chisnall 		{
837a984708SDavid Chisnall 			new_handl();
847a984708SDavid Chisnall 		}
857a984708SDavid Chisnall 		else
867a984708SDavid Chisnall 		{
877a984708SDavid Chisnall 			throw std::bad_alloc();
887a984708SDavid Chisnall 		}
897a984708SDavid Chisnall 		mem = malloc(size);
907a984708SDavid Chisnall 	}
917a984708SDavid Chisnall 
927a984708SDavid Chisnall 	return mem;
937a984708SDavid Chisnall }
947a984708SDavid Chisnall 
957a984708SDavid Chisnall __attribute__((weak))
967a984708SDavid Chisnall void* operator new(size_t size, const std::nothrow_t &) throw()
977a984708SDavid Chisnall {
987a984708SDavid Chisnall 	void *mem = malloc(size);
997a984708SDavid Chisnall 	while (0 == mem)
1007a984708SDavid Chisnall 	{
1017a984708SDavid Chisnall 		if (0 != new_handl)
1027a984708SDavid Chisnall 		{
1037a984708SDavid Chisnall 			try
1047a984708SDavid Chisnall 			{
1057a984708SDavid Chisnall 				new_handl();
1067a984708SDavid Chisnall 			}
1077a984708SDavid Chisnall 			catch (...)
1087a984708SDavid Chisnall 			{
1097a984708SDavid Chisnall 				// nothrow operator new should return NULL in case of
1107a984708SDavid Chisnall 				// std::bad_alloc exception in new handler
1117a984708SDavid Chisnall 				return NULL;
1127a984708SDavid Chisnall 			}
1137a984708SDavid Chisnall 		}
1147a984708SDavid Chisnall 		else
1157a984708SDavid Chisnall 		{
1167a984708SDavid Chisnall 			return NULL;
1177a984708SDavid Chisnall 		}
1187a984708SDavid Chisnall 		mem = malloc(size);
1197a984708SDavid Chisnall 	}
1207a984708SDavid Chisnall 
1217a984708SDavid Chisnall 	return mem;
1227a984708SDavid Chisnall }
1237a984708SDavid Chisnall 
1247a984708SDavid Chisnall 
1257a984708SDavid Chisnall __attribute__((weak))
1267a984708SDavid Chisnall void operator delete(void * ptr)
1277a984708SDavid Chisnall {
1287a984708SDavid Chisnall 	free(ptr);
1297a984708SDavid Chisnall }
1307a984708SDavid Chisnall 
1317a984708SDavid Chisnall 
1327a984708SDavid Chisnall __attribute__((weak))
1337a984708SDavid Chisnall void * operator new[](size_t size)
1347a984708SDavid Chisnall {
1357a984708SDavid Chisnall 	return ::operator new(size);
1367a984708SDavid Chisnall }
1377a984708SDavid Chisnall 
1387a984708SDavid Chisnall 
1397a984708SDavid Chisnall __attribute__((weak))
140db47c4bfSDavid Chisnall void operator delete[](void * ptr) throw()
1417a984708SDavid Chisnall {
1427a984708SDavid Chisnall 	::operator delete(ptr);
1437a984708SDavid Chisnall }
1447a984708SDavid Chisnall 
1457a984708SDavid Chisnall 
146