138fd1498Szrj // Support routines for the -*- C++ -*- dynamic memory management.
238fd1498Szrj
338fd1498Szrj // Copyright (C) 1997-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of GCC.
638fd1498Szrj //
738fd1498Szrj // GCC is free software; you can redistribute it and/or modify
838fd1498Szrj // it under the terms of the GNU General Public License as published by
938fd1498Szrj // the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj // any later version.
1138fd1498Szrj //
1238fd1498Szrj // GCC is distributed in the hope that it will be useful,
1338fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1538fd1498Szrj // GNU General Public License for more details.
1638fd1498Szrj //
1738fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1838fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1938fd1498Szrj // 3.1, as published by the Free Software Foundation.
2038fd1498Szrj
2138fd1498Szrj // You should have received a copy of the GNU General Public License and
2238fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2338fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2438fd1498Szrj // <http://www.gnu.org/licenses/>.
2538fd1498Szrj
2638fd1498Szrj #include <bits/c++config.h>
2738fd1498Szrj #include <stdlib.h>
28*58e805e6Szrj #include <stdint.h>
2938fd1498Szrj #include <bits/exception_defines.h>
3038fd1498Szrj #include "new"
3138fd1498Szrj
32*58e805e6Szrj #if !_GLIBCXX_HAVE_ALIGNED_ALLOC && !_GLIBCXX_HAVE__ALIGNED_MALLOC \
33*58e805e6Szrj && !_GLIBCXX_HAVE_POSIX_MEMALIGN && _GLIBCXX_HAVE_MEMALIGN
34*58e805e6Szrj # if _GLIBCXX_HOSTED && __has_include(<malloc.h>)
35*58e805e6Szrj // Some C libraries declare memalign in <malloc.h>
36*58e805e6Szrj # include <malloc.h>
37*58e805e6Szrj # else
38*58e805e6Szrj extern "C" void *memalign(std::size_t boundary, std::size_t size);
39*58e805e6Szrj # endif
40*58e805e6Szrj #endif
41*58e805e6Szrj
4238fd1498Szrj using std::new_handler;
4338fd1498Szrj using std::bad_alloc;
4438fd1498Szrj
45*58e805e6Szrj namespace __gnu_cxx {
46*58e805e6Szrj #if _GLIBCXX_HAVE_ALIGNED_ALLOC
47*58e805e6Szrj using ::aligned_alloc;
48*58e805e6Szrj #elif _GLIBCXX_HAVE__ALIGNED_MALLOC
49*58e805e6Szrj static inline void*
50*58e805e6Szrj aligned_alloc (std::size_t al, std::size_t sz)
51*58e805e6Szrj { return _aligned_malloc(sz, al); }
5238fd1498Szrj #elif _GLIBCXX_HAVE_POSIX_MEMALIGN
5338fd1498Szrj static inline void*
5438fd1498Szrj aligned_alloc (std::size_t al, std::size_t sz)
5538fd1498Szrj {
5638fd1498Szrj void *ptr;
57*58e805e6Szrj // posix_memalign has additional requirement, not present on aligned_alloc:
5838fd1498Szrj // The value of alignment shall be a power of two multiple of sizeof(void *).
5938fd1498Szrj if (al < sizeof(void*))
6038fd1498Szrj al = sizeof(void*);
6138fd1498Szrj int ret = posix_memalign (&ptr, al, sz);
6238fd1498Szrj if (ret == 0)
6338fd1498Szrj return ptr;
6438fd1498Szrj return nullptr;
6538fd1498Szrj }
6638fd1498Szrj #elif _GLIBCXX_HAVE_MEMALIGN
67*58e805e6Szrj static inline void*
68*58e805e6Szrj aligned_alloc (std::size_t al, std::size_t sz)
69*58e805e6Szrj {
70*58e805e6Szrj #ifdef __sun
71*58e805e6Szrj // Solaris 10 memalign requires that alignment is greater than or equal to
72*58e805e6Szrj // the size of a word.
73*58e805e6Szrj if (al < sizeof(int))
74*58e805e6Szrj al = sizeof(int);
7538fd1498Szrj #endif
76*58e805e6Szrj return memalign (al, sz);
77*58e805e6Szrj }
78*58e805e6Szrj #else // !HAVE__ALIGNED_MALLOC && !HAVE_POSIX_MEMALIGN && !HAVE_MEMALIGN
7938fd1498Szrj // The C library doesn't provide any aligned allocation functions, define one.
8038fd1498Szrj // This is a modified version of code from gcc/config/i386/gmm_malloc.h
8138fd1498Szrj static inline void*
8238fd1498Szrj aligned_alloc (std::size_t al, std::size_t sz)
8338fd1498Szrj {
8438fd1498Szrj // We need extra bytes to store the original value returned by malloc.
8538fd1498Szrj if (al < sizeof(void*))
8638fd1498Szrj al = sizeof(void*);
8738fd1498Szrj void* const malloc_ptr = malloc(sz + al);
8838fd1498Szrj if (!malloc_ptr)
8938fd1498Szrj return nullptr;
9038fd1498Szrj // Align to the requested value, leaving room for the original malloc value.
9138fd1498Szrj void* const aligned_ptr = (void *) (((uintptr_t) malloc_ptr + al) & -al);
9238fd1498Szrj
9338fd1498Szrj // Store the original malloc value where it can be found by operator delete.
9438fd1498Szrj ((void **) aligned_ptr)[-1] = malloc_ptr;
9538fd1498Szrj
9638fd1498Szrj return aligned_ptr;
9738fd1498Szrj }
9838fd1498Szrj #endif
99*58e805e6Szrj } // namespace __gnu_cxx
10038fd1498Szrj
10138fd1498Szrj _GLIBCXX_WEAK_DEFINITION void *
operator new(std::size_t sz,std::align_val_t al)10238fd1498Szrj operator new (std::size_t sz, std::align_val_t al)
10338fd1498Szrj {
10438fd1498Szrj void *p;
10538fd1498Szrj std::size_t align = (std::size_t)al;
10638fd1498Szrj
107*58e805e6Szrj /* Alignment must be a power of two. */
108*58e805e6Szrj /* XXX This should be checked by the compiler (PR 86878). */
109*58e805e6Szrj if (__builtin_expect (align & (align - 1), false))
110*58e805e6Szrj _GLIBCXX_THROW_OR_ABORT(bad_alloc());
111*58e805e6Szrj
11238fd1498Szrj /* malloc (0) is unpredictable; avoid it. */
113*58e805e6Szrj if (__builtin_expect (sz == 0, false))
11438fd1498Szrj sz = 1;
11538fd1498Szrj
11638fd1498Szrj #if _GLIBCXX_HAVE_ALIGNED_ALLOC
117*58e805e6Szrj # ifdef _AIX
118*58e805e6Szrj /* AIX 7.2.0.0 aligned_alloc incorrectly has posix_memalign's requirement
119*58e805e6Szrj * that alignment is a multiple of sizeof(void*). */
120*58e805e6Szrj if (align < sizeof(void*))
121*58e805e6Szrj align = sizeof(void*);
122*58e805e6Szrj # endif
12338fd1498Szrj /* C11: the value of size shall be an integral multiple of alignment. */
12438fd1498Szrj if (std::size_t rem = sz & (align - 1))
12538fd1498Szrj sz += align - rem;
12638fd1498Szrj #endif
12738fd1498Szrj
128*58e805e6Szrj using __gnu_cxx::aligned_alloc;
12938fd1498Szrj while (__builtin_expect ((p = aligned_alloc (align, sz)) == 0, false))
13038fd1498Szrj {
13138fd1498Szrj new_handler handler = std::get_new_handler ();
13238fd1498Szrj if (! handler)
13338fd1498Szrj _GLIBCXX_THROW_OR_ABORT(bad_alloc());
13438fd1498Szrj handler ();
13538fd1498Szrj }
13638fd1498Szrj
13738fd1498Szrj return p;
13838fd1498Szrj }
139