xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/libsupc++/eh_alloc.cc (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
1*e4b17023SJohn Marino // -*- C++ -*- Allocate exception objects.
2*e4b17023SJohn Marino // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2011
3*e4b17023SJohn Marino // Free Software Foundation, Inc.
4*e4b17023SJohn Marino //
5*e4b17023SJohn Marino // This file is part of GCC.
6*e4b17023SJohn Marino //
7*e4b17023SJohn Marino // GCC is free software; you can redistribute it and/or modify
8*e4b17023SJohn Marino // it under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino // the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino // any later version.
11*e4b17023SJohn Marino //
12*e4b17023SJohn Marino // GCC is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*e4b17023SJohn Marino // GNU General Public License for more details.
16*e4b17023SJohn Marino //
17*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
18*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
19*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
22*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
23*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino // This is derived from the C++ ABI for IA-64.  Where we diverge
27*e4b17023SJohn Marino // for cross-architecture compatibility are noted with "@@@".
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino #include <bits/c++config.h>
30*e4b17023SJohn Marino #include <cstdlib>
31*e4b17023SJohn Marino #if _GLIBCXX_HOSTED
32*e4b17023SJohn Marino #include <cstring>
33*e4b17023SJohn Marino #endif
34*e4b17023SJohn Marino #include <climits>
35*e4b17023SJohn Marino #include <exception>
36*e4b17023SJohn Marino #include "unwind-cxx.h"
37*e4b17023SJohn Marino #include <ext/concurrence.h>
38*e4b17023SJohn Marino 
39*e4b17023SJohn Marino #if _GLIBCXX_HOSTED
40*e4b17023SJohn Marino using std::free;
41*e4b17023SJohn Marino using std::malloc;
42*e4b17023SJohn Marino using std::memset;
43*e4b17023SJohn Marino #else
44*e4b17023SJohn Marino // In a freestanding environment, these functions may not be available
45*e4b17023SJohn Marino // -- but for now, we assume that they are.
46*e4b17023SJohn Marino extern "C" void *malloc (std::size_t);
47*e4b17023SJohn Marino extern "C" void free(void *);
48*e4b17023SJohn Marino extern "C" void *memset (void *, int, std::size_t);
49*e4b17023SJohn Marino #endif
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino using namespace __cxxabiv1;
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino // ??? How to control these parameters.
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino // Guess from the size of basic types how large a buffer is reasonable.
56*e4b17023SJohn Marino // Note that the basic c++ exception header has 13 pointers and 2 ints,
57*e4b17023SJohn Marino // so on a system with PSImode pointers we're talking about 56 bytes
58*e4b17023SJohn Marino // just for overhead.
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino #if INT_MAX == 32767
61*e4b17023SJohn Marino # define EMERGENCY_OBJ_SIZE	128
62*e4b17023SJohn Marino # define EMERGENCY_OBJ_COUNT	16
63*e4b17023SJohn Marino #elif LONG_MAX == 2147483647
64*e4b17023SJohn Marino # define EMERGENCY_OBJ_SIZE	512
65*e4b17023SJohn Marino # define EMERGENCY_OBJ_COUNT	32
66*e4b17023SJohn Marino #else
67*e4b17023SJohn Marino # define EMERGENCY_OBJ_SIZE	1024
68*e4b17023SJohn Marino # define EMERGENCY_OBJ_COUNT	64
69*e4b17023SJohn Marino #endif
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino #ifndef __GTHREADS
72*e4b17023SJohn Marino # undef EMERGENCY_OBJ_COUNT
73*e4b17023SJohn Marino # define EMERGENCY_OBJ_COUNT	4
74*e4b17023SJohn Marino #endif
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino #if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32
77*e4b17023SJohn Marino typedef unsigned int bitmask_type;
78*e4b17023SJohn Marino #else
79*e4b17023SJohn Marino typedef unsigned long bitmask_type;
80*e4b17023SJohn Marino #endif
81*e4b17023SJohn Marino 
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
84*e4b17023SJohn Marino static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
85*e4b17023SJohn Marino static bitmask_type emergency_used;
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT];
88*e4b17023SJohn Marino static bitmask_type dependents_used;
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino namespace
91*e4b17023SJohn Marino {
92*e4b17023SJohn Marino   // A single mutex controlling emergency allocations.
93*e4b17023SJohn Marino   __gnu_cxx::__mutex emergency_mutex;
94*e4b17023SJohn Marino }
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino extern "C" void *
__cxa_allocate_exception(std::size_t thrown_size)97*e4b17023SJohn Marino __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino   void *ret;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino   thrown_size += sizeof (__cxa_refcounted_exception);
102*e4b17023SJohn Marino   ret = malloc (thrown_size);
103*e4b17023SJohn Marino 
104*e4b17023SJohn Marino   if (! ret)
105*e4b17023SJohn Marino     {
106*e4b17023SJohn Marino       __gnu_cxx::__scoped_lock sentry(emergency_mutex);
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino       bitmask_type used = emergency_used;
109*e4b17023SJohn Marino       unsigned int which = 0;
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino       if (thrown_size > EMERGENCY_OBJ_SIZE)
112*e4b17023SJohn Marino 	goto failed;
113*e4b17023SJohn Marino       while (used & 1)
114*e4b17023SJohn Marino 	{
115*e4b17023SJohn Marino 	  used >>= 1;
116*e4b17023SJohn Marino 	  if (++which >= EMERGENCY_OBJ_COUNT)
117*e4b17023SJohn Marino 	    goto failed;
118*e4b17023SJohn Marino 	}
119*e4b17023SJohn Marino 
120*e4b17023SJohn Marino       emergency_used |= (bitmask_type)1 << which;
121*e4b17023SJohn Marino       ret = &emergency_buffer[which][0];
122*e4b17023SJohn Marino 
123*e4b17023SJohn Marino     failed:;
124*e4b17023SJohn Marino 
125*e4b17023SJohn Marino       if (!ret)
126*e4b17023SJohn Marino 	std::terminate ();
127*e4b17023SJohn Marino     }
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino   memset (ret, 0, sizeof (__cxa_refcounted_exception));
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino   return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
132*e4b17023SJohn Marino }
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino 
135*e4b17023SJohn Marino extern "C" void
__cxa_free_exception(void * vptr)136*e4b17023SJohn Marino __cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW
137*e4b17023SJohn Marino {
138*e4b17023SJohn Marino   char *base = (char *) emergency_buffer;
139*e4b17023SJohn Marino   char *ptr = (char *) vptr;
140*e4b17023SJohn Marino   if (ptr >= base
141*e4b17023SJohn Marino       && ptr < base + sizeof (emergency_buffer))
142*e4b17023SJohn Marino     {
143*e4b17023SJohn Marino       const unsigned int which
144*e4b17023SJohn Marino 	= (unsigned) (ptr - base) / EMERGENCY_OBJ_SIZE;
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino       __gnu_cxx::__scoped_lock sentry(emergency_mutex);
147*e4b17023SJohn Marino       emergency_used &= ~((bitmask_type)1 << which);
148*e4b17023SJohn Marino     }
149*e4b17023SJohn Marino   else
150*e4b17023SJohn Marino     free (ptr - sizeof (__cxa_refcounted_exception));
151*e4b17023SJohn Marino }
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino extern "C" __cxa_dependent_exception*
__cxa_allocate_dependent_exception()155*e4b17023SJohn Marino __cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW
156*e4b17023SJohn Marino {
157*e4b17023SJohn Marino   __cxa_dependent_exception *ret;
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino   ret = static_cast<__cxa_dependent_exception*>
160*e4b17023SJohn Marino     (malloc (sizeof (__cxa_dependent_exception)));
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino   if (!ret)
163*e4b17023SJohn Marino     {
164*e4b17023SJohn Marino       __gnu_cxx::__scoped_lock sentry(emergency_mutex);
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino       bitmask_type used = dependents_used;
167*e4b17023SJohn Marino       unsigned int which = 0;
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino       while (used & 1)
170*e4b17023SJohn Marino 	{
171*e4b17023SJohn Marino 	  used >>= 1;
172*e4b17023SJohn Marino 	  if (++which >= EMERGENCY_OBJ_COUNT)
173*e4b17023SJohn Marino 	    goto failed;
174*e4b17023SJohn Marino 	}
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino       dependents_used |= (bitmask_type)1 << which;
177*e4b17023SJohn Marino       ret = &dependents_buffer[which];
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino     failed:;
180*e4b17023SJohn Marino 
181*e4b17023SJohn Marino       if (!ret)
182*e4b17023SJohn Marino 	std::terminate ();
183*e4b17023SJohn Marino     }
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino   memset (ret, 0, sizeof (__cxa_dependent_exception));
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino   return ret;
188*e4b17023SJohn Marino }
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino 
191*e4b17023SJohn Marino extern "C" void
__cxa_free_dependent_exception(__cxa_dependent_exception * vptr)192*e4b17023SJohn Marino __cxxabiv1::__cxa_free_dependent_exception
193*e4b17023SJohn Marino   (__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW
194*e4b17023SJohn Marino {
195*e4b17023SJohn Marino   char *base = (char *) dependents_buffer;
196*e4b17023SJohn Marino   char *ptr = (char *) vptr;
197*e4b17023SJohn Marino   if (ptr >= base
198*e4b17023SJohn Marino       && ptr < base + sizeof (dependents_buffer))
199*e4b17023SJohn Marino     {
200*e4b17023SJohn Marino       const unsigned int which
201*e4b17023SJohn Marino 	= (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception);
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino       __gnu_cxx::__scoped_lock sentry(emergency_mutex);
204*e4b17023SJohn Marino       dependents_used &= ~((bitmask_type)1 << which);
205*e4b17023SJohn Marino     }
206*e4b17023SJohn Marino   else
207*e4b17023SJohn Marino     free (vptr);
208*e4b17023SJohn Marino }
209