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