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