xref: /freebsd/contrib/jemalloc/src/jemalloc_cpp.cpp (revision bf6039f09a30484c0749a3e3047d6a47b116b466)
1*bf6039f0SWarner Losh #include <mutex>
2*bf6039f0SWarner Losh #include <new>
3*bf6039f0SWarner Losh 
4*bf6039f0SWarner Losh #define JEMALLOC_CPP_CPP_
5*bf6039f0SWarner Losh #ifdef __cplusplus
6*bf6039f0SWarner Losh extern "C" {
7*bf6039f0SWarner Losh #endif
8*bf6039f0SWarner Losh 
9*bf6039f0SWarner Losh #include "jemalloc/internal/jemalloc_preamble.h"
10*bf6039f0SWarner Losh #include "jemalloc/internal/jemalloc_internal_includes.h"
11*bf6039f0SWarner Losh 
12*bf6039f0SWarner Losh #ifdef __cplusplus
13*bf6039f0SWarner Losh }
14*bf6039f0SWarner Losh #endif
15*bf6039f0SWarner Losh 
16*bf6039f0SWarner Losh // All operators in this file are exported.
17*bf6039f0SWarner Losh 
18*bf6039f0SWarner Losh // Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt
19*bf6039f0SWarner Losh // thunk?
20*bf6039f0SWarner Losh //
21*bf6039f0SWarner Losh // extern __typeof (sdallocx) sdallocx_int
22*bf6039f0SWarner Losh //  __attribute ((alias ("sdallocx"),
23*bf6039f0SWarner Losh //		visibility ("hidden")));
24*bf6039f0SWarner Losh //
25*bf6039f0SWarner Losh // ... but it needs to work with jemalloc namespaces.
26*bf6039f0SWarner Losh 
27*bf6039f0SWarner Losh void	*operator new(std::size_t size);
28*bf6039f0SWarner Losh void	*operator new[](std::size_t size);
29*bf6039f0SWarner Losh void	*operator new(std::size_t size, const std::nothrow_t &) noexcept;
30*bf6039f0SWarner Losh void	*operator new[](std::size_t size, const std::nothrow_t &) noexcept;
31*bf6039f0SWarner Losh void	operator delete(void *ptr) noexcept;
32*bf6039f0SWarner Losh void	operator delete[](void *ptr) noexcept;
33*bf6039f0SWarner Losh void	operator delete(void *ptr, const std::nothrow_t &) noexcept;
34*bf6039f0SWarner Losh void	operator delete[](void *ptr, const std::nothrow_t &) noexcept;
35*bf6039f0SWarner Losh 
36*bf6039f0SWarner Losh #if __cpp_sized_deallocation >= 201309
37*bf6039f0SWarner Losh /* C++14's sized-delete operators. */
38*bf6039f0SWarner Losh void	operator delete(void *ptr, std::size_t size) noexcept;
39*bf6039f0SWarner Losh void	operator delete[](void *ptr, std::size_t size) noexcept;
40*bf6039f0SWarner Losh #endif
41*bf6039f0SWarner Losh 
42*bf6039f0SWarner Losh JEMALLOC_NOINLINE
43*bf6039f0SWarner Losh static void *
44*bf6039f0SWarner Losh handleOOM(std::size_t size, bool nothrow) {
45*bf6039f0SWarner Losh 	void *ptr = nullptr;
46*bf6039f0SWarner Losh 
47*bf6039f0SWarner Losh 	while (ptr == nullptr) {
48*bf6039f0SWarner Losh 		std::new_handler handler;
49*bf6039f0SWarner Losh 		// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
50*bf6039f0SWarner Losh 		{
51*bf6039f0SWarner Losh 			static std::mutex mtx;
52*bf6039f0SWarner Losh 			std::lock_guard<std::mutex> lock(mtx);
53*bf6039f0SWarner Losh 
54*bf6039f0SWarner Losh 			handler = std::set_new_handler(nullptr);
55*bf6039f0SWarner Losh 			std::set_new_handler(handler);
56*bf6039f0SWarner Losh 		}
57*bf6039f0SWarner Losh 		if (handler == nullptr)
58*bf6039f0SWarner Losh 			break;
59*bf6039f0SWarner Losh 
60*bf6039f0SWarner Losh 		try {
61*bf6039f0SWarner Losh 			handler();
62*bf6039f0SWarner Losh 		} catch (const std::bad_alloc &) {
63*bf6039f0SWarner Losh 			break;
64*bf6039f0SWarner Losh 		}
65*bf6039f0SWarner Losh 
66*bf6039f0SWarner Losh 		ptr = je_malloc(size);
67*bf6039f0SWarner Losh 	}
68*bf6039f0SWarner Losh 
69*bf6039f0SWarner Losh 	if (ptr == nullptr && !nothrow)
70*bf6039f0SWarner Losh 		std::__throw_bad_alloc();
71*bf6039f0SWarner Losh 	return ptr;
72*bf6039f0SWarner Losh }
73*bf6039f0SWarner Losh 
74*bf6039f0SWarner Losh template <bool IsNoExcept>
75*bf6039f0SWarner Losh JEMALLOC_ALWAYS_INLINE
76*bf6039f0SWarner Losh void *
77*bf6039f0SWarner Losh newImpl(std::size_t size) noexcept(IsNoExcept) {
78*bf6039f0SWarner Losh 	void *ptr = je_malloc(size);
79*bf6039f0SWarner Losh 	if (likely(ptr != nullptr))
80*bf6039f0SWarner Losh 		return ptr;
81*bf6039f0SWarner Losh 
82*bf6039f0SWarner Losh 	return handleOOM(size, IsNoExcept);
83*bf6039f0SWarner Losh }
84*bf6039f0SWarner Losh 
85*bf6039f0SWarner Losh void *
86*bf6039f0SWarner Losh operator new(std::size_t size) {
87*bf6039f0SWarner Losh 	return newImpl<false>(size);
88*bf6039f0SWarner Losh }
89*bf6039f0SWarner Losh 
90*bf6039f0SWarner Losh void *
91*bf6039f0SWarner Losh operator new[](std::size_t size) {
92*bf6039f0SWarner Losh 	return newImpl<false>(size);
93*bf6039f0SWarner Losh }
94*bf6039f0SWarner Losh 
95*bf6039f0SWarner Losh void *
96*bf6039f0SWarner Losh operator new(std::size_t size, const std::nothrow_t &) noexcept {
97*bf6039f0SWarner Losh 	return newImpl<true>(size);
98*bf6039f0SWarner Losh }
99*bf6039f0SWarner Losh 
100*bf6039f0SWarner Losh void *
101*bf6039f0SWarner Losh operator new[](std::size_t size, const std::nothrow_t &) noexcept {
102*bf6039f0SWarner Losh 	return newImpl<true>(size);
103*bf6039f0SWarner Losh }
104*bf6039f0SWarner Losh 
105*bf6039f0SWarner Losh void
106*bf6039f0SWarner Losh operator delete(void *ptr) noexcept {
107*bf6039f0SWarner Losh 	je_free(ptr);
108*bf6039f0SWarner Losh }
109*bf6039f0SWarner Losh 
110*bf6039f0SWarner Losh void
111*bf6039f0SWarner Losh operator delete[](void *ptr) noexcept {
112*bf6039f0SWarner Losh 	je_free(ptr);
113*bf6039f0SWarner Losh }
114*bf6039f0SWarner Losh 
115*bf6039f0SWarner Losh void
116*bf6039f0SWarner Losh operator delete(void *ptr, const std::nothrow_t &) noexcept {
117*bf6039f0SWarner Losh 	je_free(ptr);
118*bf6039f0SWarner Losh }
119*bf6039f0SWarner Losh 
120*bf6039f0SWarner Losh void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
121*bf6039f0SWarner Losh 	je_free(ptr);
122*bf6039f0SWarner Losh }
123*bf6039f0SWarner Losh 
124*bf6039f0SWarner Losh #if __cpp_sized_deallocation >= 201309
125*bf6039f0SWarner Losh 
126*bf6039f0SWarner Losh void
127*bf6039f0SWarner Losh operator delete(void *ptr, std::size_t size) noexcept {
128*bf6039f0SWarner Losh 	if (unlikely(ptr == nullptr)) {
129*bf6039f0SWarner Losh 		return;
130*bf6039f0SWarner Losh 	}
131*bf6039f0SWarner Losh 	je_sdallocx_noflags(ptr, size);
132*bf6039f0SWarner Losh }
133*bf6039f0SWarner Losh 
134*bf6039f0SWarner Losh void operator delete[](void *ptr, std::size_t size) noexcept {
135*bf6039f0SWarner Losh 	if (unlikely(ptr == nullptr)) {
136*bf6039f0SWarner Losh 		return;
137*bf6039f0SWarner Losh 	}
138*bf6039f0SWarner Losh 	je_sdallocx_noflags(ptr, size);
139*bf6039f0SWarner Losh }
140*bf6039f0SWarner Losh 
141*bf6039f0SWarner Losh #endif  // __cpp_sized_deallocation
142