eh_alloc.cc revision 132720
197403Sobrien// -*- C++ -*- Allocate exception objects. 2132720Skan// Copyright (C) 2001, 2004 Free Software Foundation, Inc. 397403Sobrien// 4132720Skan// This file is part of GCC. 597403Sobrien// 6132720Skan// GCC is free software; you can redistribute it and/or modify 797403Sobrien// it under the terms of the GNU General Public License as published by 897403Sobrien// the Free Software Foundation; either version 2, or (at your option) 997403Sobrien// any later version. 1097403Sobrien// 11132720Skan// GCC is distributed in the hope that it will be useful, 1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1497403Sobrien// GNU General Public License for more details. 1597403Sobrien// 1697403Sobrien// You should have received a copy of the GNU General Public License 17132720Skan// along with GCC; see the file COPYING. If not, write to 1897403Sobrien// the Free Software Foundation, 59 Temple Place - Suite 330, 1997403Sobrien// Boston, MA 02111-1307, USA. 2097403Sobrien 2197403Sobrien// As a special exception, you may use this file as part of a free software 2297403Sobrien// library without restriction. Specifically, if other files instantiate 2397403Sobrien// templates or use macros or inline functions from this file, or you compile 2497403Sobrien// this file and link it with other files to produce an executable, this 2597403Sobrien// file does not by itself cause the resulting executable to be covered by 2697403Sobrien// the GNU General Public License. This exception does not however 2797403Sobrien// invalidate any other reasons why the executable file might be covered by 2897403Sobrien// the GNU General Public License. 2997403Sobrien 3097403Sobrien// This is derived from the C++ ABI for IA-64. Where we diverge 3197403Sobrien// for cross-architecture compatibility are noted with "@@@". 3297403Sobrien 3397403Sobrien#include <cstdlib> 3497403Sobrien#include <cstring> 3597403Sobrien#include <climits> 36102782Skan#include <exception> 3797403Sobrien#include "unwind-cxx.h" 3897403Sobrien#include "bits/c++config.h" 3997403Sobrien#include "bits/gthr.h" 4097403Sobrien 4197403Sobrienusing namespace __cxxabiv1; 4297403Sobrien 4397403Sobrien 4497403Sobrien// ??? How to control these parameters. 4597403Sobrien 4697403Sobrien// Guess from the size of basic types how large a buffer is reasonable. 4797403Sobrien// Note that the basic c++ exception header has 13 pointers and 2 ints, 4897403Sobrien// so on a system with PSImode pointers we're talking about 56 bytes 4997403Sobrien// just for overhead. 5097403Sobrien 5197403Sobrien#if INT_MAX == 32767 5297403Sobrien# define EMERGENCY_OBJ_SIZE 128 5397403Sobrien# define EMERGENCY_OBJ_COUNT 16 5497403Sobrien#elif LONG_MAX == 2147483647 5597403Sobrien# define EMERGENCY_OBJ_SIZE 512 5697403Sobrien# define EMERGENCY_OBJ_COUNT 32 5797403Sobrien#else 5897403Sobrien# define EMERGENCY_OBJ_SIZE 1024 5997403Sobrien# define EMERGENCY_OBJ_COUNT 64 6097403Sobrien#endif 6197403Sobrien 6297403Sobrien#ifndef __GTHREADS 6397403Sobrien# undef EMERGENCY_OBJ_COUNT 6497403Sobrien# define EMERGENCY_OBJ_COUNT 4 6597403Sobrien#endif 6697403Sobrien 6797403Sobrien#if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32 6897403Sobrientypedef unsigned int bitmask_type; 6997403Sobrien#else 7097403Sobrientypedef unsigned long bitmask_type; 7197403Sobrien#endif 7297403Sobrien 7397403Sobrien 7497403Sobrientypedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned)); 7597403Sobrienstatic one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT]; 7697403Sobrienstatic bitmask_type emergency_used; 7797403Sobrien 7897403Sobrien 7997403Sobrien#ifdef __GTHREADS 8097403Sobrien#ifdef __GTHREAD_MUTEX_INIT 8197403Sobrienstatic __gthread_mutex_t emergency_mutex =__GTHREAD_MUTEX_INIT; 8297403Sobrien#else 8397403Sobrienstatic __gthread_mutex_t emergency_mutex; 8497403Sobrien#endif 8597403Sobrien 8697403Sobrien#ifdef __GTHREAD_MUTEX_INIT_FUNCTION 8797403Sobrienstatic void 8897403Sobrienemergency_mutex_init () 8997403Sobrien{ 9097403Sobrien __GTHREAD_MUTEX_INIT_FUNCTION (&emergency_mutex); 9197403Sobrien} 9297403Sobrien#endif 9397403Sobrien#endif 9497403Sobrien 9597403Sobrien 9697403Sobrienextern "C" void * 97132720Skan__cxa_allocate_exception(std::size_t thrown_size) throw() 9897403Sobrien{ 9997403Sobrien void *ret; 10097403Sobrien 10197403Sobrien thrown_size += sizeof (__cxa_exception); 10297403Sobrien ret = std::malloc (thrown_size); 10397403Sobrien 10497403Sobrien if (! ret) 10597403Sobrien { 10697403Sobrien#ifdef __GTHREADS 10797403Sobrien#ifdef __GTHREAD_MUTEX_INIT_FUNCTION 10897403Sobrien static __gthread_once_t once = __GTHREAD_ONCE_INIT; 10997403Sobrien __gthread_once (&once, emergency_mutex_init); 11097403Sobrien#endif 11197403Sobrien __gthread_mutex_lock (&emergency_mutex); 11297403Sobrien#endif 11397403Sobrien 11497403Sobrien bitmask_type used = emergency_used; 11597403Sobrien unsigned int which = 0; 11697403Sobrien 11797403Sobrien if (thrown_size > EMERGENCY_OBJ_SIZE) 11897403Sobrien goto failed; 11997403Sobrien while (used & 1) 12097403Sobrien { 12197403Sobrien used >>= 1; 12297403Sobrien if (++which >= EMERGENCY_OBJ_COUNT) 12397403Sobrien goto failed; 12497403Sobrien } 12597403Sobrien 12697403Sobrien emergency_used |= (bitmask_type)1 << which; 12797403Sobrien ret = &emergency_buffer[which][0]; 12897403Sobrien 12997403Sobrien failed:; 13097403Sobrien#ifdef __GTHREADS 13197403Sobrien __gthread_mutex_unlock (&emergency_mutex); 13297403Sobrien#endif 13397403Sobrien if (!ret) 13497403Sobrien std::terminate (); 13597403Sobrien } 13697403Sobrien 13797403Sobrien std::memset (ret, 0, sizeof (__cxa_exception)); 13897403Sobrien 13997403Sobrien return (void *)((char *)ret + sizeof (__cxa_exception)); 14097403Sobrien} 14197403Sobrien 14297403Sobrien 14397403Sobrienextern "C" void 144132720Skan__cxa_free_exception(void *vptr) throw() 14597403Sobrien{ 14697403Sobrien char *ptr = (char *) vptr; 14797403Sobrien if (ptr >= &emergency_buffer[0][0] 14897403Sobrien && ptr < &emergency_buffer[0][0] + sizeof (emergency_buffer)) 14997403Sobrien { 15097403Sobrien unsigned int which 15197403Sobrien = (unsigned)(ptr - &emergency_buffer[0][0]) / EMERGENCY_OBJ_SIZE; 15297403Sobrien 15397403Sobrien#ifdef __GTHREADS 15497403Sobrien __gthread_mutex_lock (&emergency_mutex); 15597403Sobrien emergency_used &= ~((bitmask_type)1 << which); 15697403Sobrien __gthread_mutex_unlock (&emergency_mutex); 15797403Sobrien#else 15897403Sobrien emergency_used &= ~((bitmask_type)1 << which); 15997403Sobrien#endif 16097403Sobrien } 16197403Sobrien else 16297403Sobrien std::free (ptr - sizeof (__cxa_exception)); 16397403Sobrien} 164