b0b5524045ee021673884325307c8c56b8686f25
[platform/framework/web/crosswalk.git] / src / third_party / libc++abi / trunk / src / cxa_exception_storage.cpp
1 //===--------------------- 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
18 namespace __cxxabiv1 {
19
20 namespace {
21     __cxa_eh_globals * __globals () {
22         static thread_local __cxa_eh_globals eh_globals;
23         return &eh_globals;
24         }
25     }
26
27 extern "C" {
28     __cxa_eh_globals * __cxa_get_globals      () { return __globals (); }
29     __cxa_eh_globals * __cxa_get_globals_fast () { return __globals (); }
30     }
31 }
32
33 #else
34
35 #include <pthread.h>
36 #include <cstdlib>          // for calloc, free
37 #include "abort_message.h"
38
39 //  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.
42
43 namespace __cxxabiv1 {
44 namespace {
45     pthread_key_t  key_;
46     pthread_once_t flag_ = PTHREAD_ONCE_INIT;
47
48     void destruct_ (void *p) {
49         std::free ( p );
50         if ( 0 != ::pthread_setspecific ( key_, NULL ) ) 
51             abort_message("cannot zero out thread value for __cxa_get_globals()");
52         }
53
54     void construct_ () {
55         if ( 0 != pthread_key_create ( &key_, destruct_ ) )
56             abort_message("cannot create pthread key for __cxa_get_globals()");
57         }
58 }   
59
60 extern "C" {
61     __cxa_eh_globals * __cxa_get_globals () {
62     //  Try to get the globals for this thread
63         __cxa_eh_globals* retVal = __cxa_get_globals_fast ();
64     
65     //  If this is the first time we've been asked for these globals, create them
66         if ( NULL == retVal ) {
67             retVal = static_cast<__cxa_eh_globals*>
68                         (std::calloc (1, sizeof (__cxa_eh_globals)));
69             if ( NULL == retVal )
70                 abort_message("cannot allocate __cxa_eh_globals");
71             if ( 0 != pthread_setspecific ( key_, retVal ) )
72                abort_message("pthread_setspecific failure in __cxa_get_globals()");
73            }
74         return retVal;
75         }
76
77     // Note that this implementation will reliably return NULL if not
78     // preceded by a call to __cxa_get_globals().  This is an extension
79     // to the Itanium ABI and is taken advantage of in several places in
80     // libc++abi.
81     __cxa_eh_globals * __cxa_get_globals_fast () {
82     //  First time through, create the key.
83         if (0 != pthread_once(&flag_, construct_))
84             abort_message("pthread_once failure in __cxa_get_globals_fast()");
85 //        static int init = construct_();
86         return static_cast<__cxa_eh_globals*>(::pthread_getspecific(key_));
87         }
88     
89 }
90 }
91 #endif