00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <exception>
00034 #include <cstdlib>
00035 #include <cstring>
00036 #include <limits.h>
00037 #include "unwind-cxx.h"
00038 #include "bits/c++config.h"
00039 #include "bits/gthr.h"
00040
00041 using namespace __cxxabiv1;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #if INT_MAX == 32767
00052 # define EMERGENCY_OBJ_SIZE 128
00053 # define EMERGENCY_OBJ_COUNT 16
00054 #elif LONG_MAX == 2147483647
00055 # define EMERGENCY_OBJ_SIZE 512
00056 # define EMERGENCY_OBJ_COUNT 32
00057 #else
00058 # define EMERGENCY_OBJ_SIZE 1024
00059 # define EMERGENCY_OBJ_COUNT 64
00060 #endif
00061
00062 #ifndef __GTHREADS
00063 # undef EMERGENCY_OBJ_COUNT
00064 # define EMERGENCY_OBJ_COUNT 4
00065 #endif
00066
00067 #if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32
00068 typedef unsigned int bitmask_type;
00069 #else
00070 typedef unsigned long bitmask_type;
00071 #endif
00072
00073
00074 typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
00075 static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
00076 static bitmask_type emergency_used;
00077
00078
00079 #ifdef __GTHREADS
00080 #ifdef __GTHREAD_MUTEX_INIT
00081 static __gthread_mutex_t emergency_mutex =__GTHREAD_MUTEX_INIT;
00082 #else
00083 static __gthread_mutex_t emergency_mutex;
00084 #endif
00085
00086 #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
00087 static void
00088 emergency_mutex_init ()
00089 {
00090 __GTHREAD_MUTEX_INIT_FUNCTION (&emergency_mutex);
00091 }
00092 #endif
00093 #endif
00094
00095
00096 extern "C" void *
00097 __cxa_allocate_exception(std::size_t thrown_size)
00098 {
00099 void *ret;
00100
00101 thrown_size += sizeof (__cxa_exception);
00102 ret = std::malloc (thrown_size);
00103
00104 if (! ret)
00105 {
00106 #ifdef __GTHREADS
00107 #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
00108 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
00109 __gthread_once (&once, emergency_mutex_init);
00110 #endif
00111 __gthread_mutex_lock (&emergency_mutex);
00112 #endif
00113
00114 bitmask_type used = emergency_used;
00115 unsigned int which = 0;
00116
00117 if (thrown_size > EMERGENCY_OBJ_SIZE)
00118 goto failed;
00119 while (used & 1)
00120 {
00121 used >>= 1;
00122 if (++which >= EMERGENCY_OBJ_COUNT)
00123 goto failed;
00124 }
00125
00126 emergency_used |= (bitmask_type)1 << which;
00127 ret = &emergency_buffer[which][0];
00128
00129 failed:;
00130 #ifdef __GTHREADS
00131 __gthread_mutex_unlock (&emergency_mutex);
00132 #endif
00133 if (!ret)
00134 std::terminate ();
00135 }
00136
00137 std::memset (ret, 0, sizeof (__cxa_exception));
00138
00139 return (void *)((char *)ret + sizeof (__cxa_exception));
00140 }
00141
00142
00143 extern "C" void
00144 __cxa_free_exception(void *vptr)
00145 {
00146 char *ptr = (char *) vptr;
00147 if (ptr >= &emergency_buffer[0][0]
00148 && ptr < &emergency_buffer[0][0] + sizeof (emergency_buffer))
00149 {
00150 unsigned int which
00151 = (unsigned)(ptr - &emergency_buffer[0][0]) / EMERGENCY_OBJ_SIZE;
00152
00153 #ifdef __GTHREADS
00154 __gthread_mutex_lock (&emergency_mutex);
00155 emergency_used &= ~((bitmask_type)1 << which);
00156 __gthread_mutex_unlock (&emergency_mutex);
00157 #else
00158 emergency_used &= ~((bitmask_type)1 << which);
00159 #endif
00160 }
00161 else
00162 std::free (ptr - sizeof (__cxa_exception));
00163 }