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