blob: d648f295b341d4cf181adf9430d2f43fe2177285 [file] [log] [blame]
Marshall Clow61b898e2011-07-20 14:53:53 +00001//===--------------------- cxa_exception_storage.cpp ----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// This file implements the storage for the "Caught Exception Stack"
10// http://www.codesourcery.com/public/cxx-abi/abi-eh.html (section 2.2.2)
11//
12//===----------------------------------------------------------------------===//
13
14#include "cxa_exception.hpp"
15
16#ifdef HAS_THREAD_LOCAL
17
18namespace __cxxabiv1 {
19
20namespace {
21 __cxa_eh_globals * __globals () throw () {
22 static thread_local __cxa_eh_globals eh_globals;
23 return &eh_globals;
24 }
25 }
26
27extern "C" {
28 __cxa_eh_globals * __cxa_get_globals () throw() { return __globals (); }
29 __cxa_eh_globals * __cxa_get_globals_fast () throw() { return __globals (); }
30 }
31}
32
33#else
34
35#include <pthread.h>
36#include <cstdlib> // for calloc, free
Nick Kledzikf4429fe2011-08-02 01:34:26 +000037#include "abort_message.h"
Marshall Clow61b898e2011-07-20 14:53:53 +000038
Nick Kledzikf4429fe2011-08-02 01:34:26 +000039// In general, we treat all pthread errors as fatal.
40// We cannot call std::terminate() because that will in turn
41// call __cxa_get_globals() and cause infinite recursion.
Marshall Clow61b898e2011-07-20 14:53:53 +000042
43namespace __cxxabiv1 {
44namespace {
Marshall Clow61b898e2011-07-20 14:53:53 +000045 pthread_key_t key_;
46
47 void destruct_ (void *p) throw () {
48 std::free ( p );
Nick Kledzikf4429fe2011-08-02 01:34:26 +000049 if ( 0 != ::pthread_setspecific ( key_, NULL ) )
50 abort_message("cannot zero out thread value for __cxa_get_globals()");
Marshall Clow61b898e2011-07-20 14:53:53 +000051 }
52
Howard Hinnant928afcd2012-01-23 23:55:58 +000053 int construct_ () throw () {
Nick Kledzikf4429fe2011-08-02 01:34:26 +000054 if ( 0 != pthread_key_create ( &key_, destruct_ ) )
55 abort_message("cannot create pthread key for __cxa_get_globals()");
Howard Hinnant928afcd2012-01-23 23:55:58 +000056 return 0;
Marshall Clow61b898e2011-07-20 14:53:53 +000057 }
58}
59
60extern "C" {
61 __cxa_eh_globals * __cxa_get_globals () throw () {
Marshall Clow61b898e2011-07-20 14:53:53 +000062
63 // Try to get the globals for this thread
64 __cxa_eh_globals* retVal = __cxa_get_globals_fast ();
65
66 // If this is the first time we've been asked for these globals, create them
67 if ( NULL == retVal ) {
68 retVal = static_cast<__cxa_eh_globals*>
69 (std::calloc (1, sizeof (__cxa_eh_globals)));
Nick Kledzikf4429fe2011-08-02 01:34:26 +000070 if ( NULL == retVal )
71 abort_message("cannot allocate __cxa_eh_globals");
72 if ( 0 != pthread_setspecific ( key_, retVal ) )
73 abort_message("pthread_setspecific failure in __cxa_get_globals()");
74 }
Marshall Clow61b898e2011-07-20 14:53:53 +000075 return retVal;
76 }
77
78 __cxa_eh_globals * __cxa_get_globals_fast () throw () {
Howard Hinnant928afcd2012-01-23 23:55:58 +000079 // First time through, create the key.
80 static int init = construct_();
Marshall Clow61b898e2011-07-20 14:53:53 +000081 return static_cast<__cxa_eh_globals*>(::pthread_getspecific(key_));
82 }
83
84}
85}
86#endif