xref: /openbsd-src/gnu/gcc/libstdc++-v3/libsupc++/eh_alloc.cc (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert // -*- C++ -*- Allocate exception objects.
2*404b540aSrobert // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
3*404b540aSrobert // Free Software Foundation, Inc.
4*404b540aSrobert //
5*404b540aSrobert // This file is part of GCC.
6*404b540aSrobert //
7*404b540aSrobert // GCC is free software; you can redistribute it and/or modify
8*404b540aSrobert // it under the terms of the GNU General Public License as published by
9*404b540aSrobert // the Free Software Foundation; either version 2, or (at your option)
10*404b540aSrobert // any later version.
11*404b540aSrobert //
12*404b540aSrobert // GCC is distributed in the hope that it will be useful,
13*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of
14*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*404b540aSrobert // GNU General Public License for more details.
16*404b540aSrobert //
17*404b540aSrobert // You should have received a copy of the GNU General Public License
18*404b540aSrobert // along with GCC; see the file COPYING.  If not, write to
19*404b540aSrobert // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20*404b540aSrobert // Boston, MA 02110-1301, USA.
21*404b540aSrobert 
22*404b540aSrobert // As a special exception, you may use this file as part of a free software
23*404b540aSrobert // library without restriction.  Specifically, if other files instantiate
24*404b540aSrobert // templates or use macros or inline functions from this file, or you compile
25*404b540aSrobert // this file and link it with other files to produce an executable, this
26*404b540aSrobert // file does not by itself cause the resulting executable to be covered by
27*404b540aSrobert // the GNU General Public License.  This exception does not however
28*404b540aSrobert // invalidate any other reasons why the executable file might be covered by
29*404b540aSrobert // the GNU General Public License.
30*404b540aSrobert 
31*404b540aSrobert // This is derived from the C++ ABI for IA-64.  Where we diverge
32*404b540aSrobert // for cross-architecture compatibility are noted with "@@@".
33*404b540aSrobert 
34*404b540aSrobert #include <bits/c++config.h>
35*404b540aSrobert #include <cstdlib>
36*404b540aSrobert #if _GLIBCXX_HOSTED
37*404b540aSrobert #include <cstring>
38*404b540aSrobert #endif
39*404b540aSrobert #include <climits>
40*404b540aSrobert #include <exception>
41*404b540aSrobert #include "unwind-cxx.h"
42*404b540aSrobert #include <ext/concurrence.h>
43*404b540aSrobert 
44*404b540aSrobert #if _GLIBCXX_HOSTED
45*404b540aSrobert using std::free;
46*404b540aSrobert using std::malloc;
47*404b540aSrobert using std::memset;
48*404b540aSrobert #else
49*404b540aSrobert // In a freestanding environment, these functions may not be available
50*404b540aSrobert // -- but for now, we assume that they are.
51*404b540aSrobert extern "C" void *malloc (std::size_t);
52*404b540aSrobert extern "C" void free(void *);
53*404b540aSrobert extern "C" void *memset (void *, int, std::size_t);
54*404b540aSrobert #endif
55*404b540aSrobert 
56*404b540aSrobert using namespace __cxxabiv1;
57*404b540aSrobert 
58*404b540aSrobert // ??? How to control these parameters.
59*404b540aSrobert 
60*404b540aSrobert // Guess from the size of basic types how large a buffer is reasonable.
61*404b540aSrobert // Note that the basic c++ exception header has 13 pointers and 2 ints,
62*404b540aSrobert // so on a system with PSImode pointers we're talking about 56 bytes
63*404b540aSrobert // just for overhead.
64*404b540aSrobert 
65*404b540aSrobert #if INT_MAX == 32767
66*404b540aSrobert # define EMERGENCY_OBJ_SIZE	128
67*404b540aSrobert # define EMERGENCY_OBJ_COUNT	16
68*404b540aSrobert #elif LONG_MAX == 2147483647
69*404b540aSrobert # define EMERGENCY_OBJ_SIZE	512
70*404b540aSrobert # define EMERGENCY_OBJ_COUNT	32
71*404b540aSrobert #else
72*404b540aSrobert # define EMERGENCY_OBJ_SIZE	1024
73*404b540aSrobert # define EMERGENCY_OBJ_COUNT	64
74*404b540aSrobert #endif
75*404b540aSrobert 
76*404b540aSrobert #ifndef __GTHREADS
77*404b540aSrobert # undef EMERGENCY_OBJ_COUNT
78*404b540aSrobert # define EMERGENCY_OBJ_COUNT	4
79*404b540aSrobert #endif
80*404b540aSrobert 
81*404b540aSrobert #if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32
82*404b540aSrobert typedef unsigned int bitmask_type;
83*404b540aSrobert #else
84*404b540aSrobert typedef unsigned long bitmask_type;
85*404b540aSrobert #endif
86*404b540aSrobert 
87*404b540aSrobert 
88*404b540aSrobert typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
89*404b540aSrobert static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
90*404b540aSrobert static bitmask_type emergency_used;
91*404b540aSrobert 
92*404b540aSrobert namespace
93*404b540aSrobert {
94*404b540aSrobert   // A single mutex controlling emergency allocations.
95*404b540aSrobert   __gnu_cxx::__mutex emergency_mutex;
96*404b540aSrobert }
97*404b540aSrobert 
98*404b540aSrobert extern "C" void *
__cxa_allocate_exception(std::size_t thrown_size)99*404b540aSrobert __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
100*404b540aSrobert {
101*404b540aSrobert   void *ret;
102*404b540aSrobert 
103*404b540aSrobert   thrown_size += sizeof (__cxa_exception);
104*404b540aSrobert   ret = malloc (thrown_size);
105*404b540aSrobert 
106*404b540aSrobert   if (! ret)
107*404b540aSrobert     {
108*404b540aSrobert       __gnu_cxx::__scoped_lock sentry(emergency_mutex);
109*404b540aSrobert 
110*404b540aSrobert       bitmask_type used = emergency_used;
111*404b540aSrobert       unsigned int which = 0;
112*404b540aSrobert 
113*404b540aSrobert       if (thrown_size > EMERGENCY_OBJ_SIZE)
114*404b540aSrobert 	goto failed;
115*404b540aSrobert       while (used & 1)
116*404b540aSrobert 	{
117*404b540aSrobert 	  used >>= 1;
118*404b540aSrobert 	  if (++which >= EMERGENCY_OBJ_COUNT)
119*404b540aSrobert 	    goto failed;
120*404b540aSrobert 	}
121*404b540aSrobert 
122*404b540aSrobert       emergency_used |= (bitmask_type)1 << which;
123*404b540aSrobert       ret = &emergency_buffer[which][0];
124*404b540aSrobert 
125*404b540aSrobert     failed:;
126*404b540aSrobert 
127*404b540aSrobert       if (!ret)
128*404b540aSrobert 	std::terminate ();
129*404b540aSrobert     }
130*404b540aSrobert 
131*404b540aSrobert   // We have an uncaught exception as soon as we allocate memory.  This
132*404b540aSrobert   // yields uncaught_exception() true during the copy-constructor that
133*404b540aSrobert   // initializes the exception object.  See Issue 475.
134*404b540aSrobert   __cxa_eh_globals *globals = __cxa_get_globals ();
135*404b540aSrobert   globals->uncaughtExceptions += 1;
136*404b540aSrobert 
137*404b540aSrobert   memset (ret, 0, sizeof (__cxa_exception));
138*404b540aSrobert 
139*404b540aSrobert   return (void *)((char *)ret + sizeof (__cxa_exception));
140*404b540aSrobert }
141*404b540aSrobert 
142*404b540aSrobert 
143*404b540aSrobert extern "C" void
__cxa_free_exception(void * vptr)144*404b540aSrobert __cxxabiv1::__cxa_free_exception(void *vptr) throw()
145*404b540aSrobert {
146*404b540aSrobert   char *ptr = (char *) vptr;
147*404b540aSrobert   if (ptr >= &emergency_buffer[0][0]
148*404b540aSrobert       && ptr < &emergency_buffer[0][0] + sizeof (emergency_buffer))
149*404b540aSrobert     {
150*404b540aSrobert       const unsigned int which
151*404b540aSrobert 	= (unsigned)(ptr - &emergency_buffer[0][0]) / EMERGENCY_OBJ_SIZE;
152*404b540aSrobert 
153*404b540aSrobert       __gnu_cxx::__scoped_lock sentry(emergency_mutex);
154*404b540aSrobert       emergency_used &= ~((bitmask_type)1 << which);
155*404b540aSrobert     }
156*404b540aSrobert   else
157*404b540aSrobert     free (ptr - sizeof (__cxa_exception));
158*404b540aSrobert }
159